diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 5057640..9f119f9 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-11T11:02:00","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-13T11:45:53","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/10-full-guide/index.html b/dev/10-full-guide/index.html index 80946cc..fa5894c 100644 --- a/dev/10-full-guide/index.html +++ b/dev/10-full-guide/index.html @@ -13,12 +13,12 @@ git add . git commit -m "First commit" pre-commit install # Future commits can't be directly to main unless you use -n

Now, create a new repository on GitHub and push your code. We won't give you details on how to do this, but you can check The Turing Way.

After that, jump on to Setting up your package.

Applying to an existing package

To apply the template to an existing package, you can do the following:

git

This assumes that you already use git on that package and the your working directory is clean. It will fail otherwise.

julia> using BestieTemplate
-julia> BestieTemplate.apply("full/path/to/YourPackage.jl")

This command will look around your project path and try to guess some of the answers. Currently, we guess:

Overwrite

You will be asked whether to overwrite existing files or not. Since you are using git, you can try it out and reset if you don't like the result.

If you don't like the result, or want to override the answers, you can run the apply function with additional arguments, for instance:

julia> data = Dict("Authors" => "Bob <bob@bob.br>")
-julia> BestieTemplate.apply("full/path/to/YourPackage.jl", data)

Alternatively, you can also tell Bestie to not guess:

julia> BestieTemplate.apply("full/path/to/YourPackage.jl"; guess = false)

See the full docstring for BestieTemplate.apply for more information.

You will most likely have conflicts when you apply the template. Whenever a conflict appears, you will need to decide on whether to accept or reject the new changes. Unfortunately, they are not shown to you when the conflict appears, so the best solution is to just accept all of them and then fix the conflicts using git.

Review the changes

Don't just add the changes blindly, because some of your files can and will be overwritten.

README.md conflicts

We really can't avoid some conflicts, and although some file can be skipped if existing (such as CITATION.cff), some can't. For instance, README.md will most likely be wrong when you apply the template, but the badges (for instance), need to be included in your project. This means that README.md cannot be skipped, and you will have to accept the overwrite and manually fix your README.md.

Formatting

You might most likely see changes in the formatting. So if you have are a formatter, it might be best to run it before reviewing the changes. If you have chosen the "Recommended" answers, or explicitly chose to add pre-commit, then you should use it now (see below).

If you need some help with undoing some of these changes, I recommend using a graphical interface. After the template is applied and you are happy with the conflict resolution, enable pre-commit and push your code.

git add .
+julia> BestieTemplate.apply("full/path/to/YourPackage.jl")

This command will look around your project path and try to guess some of the answers. Currently, we guess:

Overwrite

You will be asked whether to overwrite existing files or not. Since you are using git, you can try it out and reset if you don't like the result. So we recommend overwriting at this point.

If you don't like the result, or want to override the answers, you can run the apply function with additional arguments, for instance:

julia> data = Dict("Authors" => "Bob <bob@bob.br>")
+julia> BestieTemplate.apply("full/path/to/YourPackage.jl", data)

Alternatively, you can also tell Bestie to not guess:

julia> BestieTemplate.apply("full/path/to/YourPackage.jl"; guess = false)

See the full docstring for BestieTemplate.apply for more information.

Review the changes

Don't just add the changes blindly, because some of your files can and will be overwritten.

README.md conflicts

We really can't avoid some conflicts, and although some file can be skipped if existing (such as CITATION.cff), some can't. For instance, README.md will most likely be wrong when you apply the template, but the badges (for instance), need to be included in your project. This means that README.md cannot be skipped, and you will have to accept the overwrite and manually fix your README.md.

Formatting

You might most likely see changes in the formatting. So if you have a formatter, it might be best to run it before reviewing the changes. If you have chosen the "Recommended" answers, or explicitly chose to add pre-commit, then you should use it now (see below).

If you need some help with undoing some of these changes, I recommend using a graphical interface for git. After the template is applied and you are happy with the conflict resolution, enable pre-commit and push your code.

git add .
 pre-commit run -a # Try to fix possible pre-commit issues (failures are expected)
 pre-commit install # All commits will run pre-commit now
 git add .
-git commit -m "Apply BestieTemplate vx.y.z"

Push your code to GitHub and head to Setting up your package for information on what to do next.

Now, go to Setting up your package to check what you still need to configure for your package.

Updating

To update the package, simply call

julia> BestieTemplate.update()

You will be asked the relevant questions of the package as if you had applied it. The big differences are:

Change previous answers

You can change your previous answers. In other words, if you though something was not mature enough in the past, but you are more confident in that now, you can adopt it now. This works even if the template was not updated itself.

As with the first application, you need to run pre-commit run -a to fix the unavoidable linting and formatting issues. Check the modifications in the relevant linter and formatting files, if you changed them manually, before doing it, though.

pre-commit run -a

The underlying package copier will use git to apply the differences and it will overwrite whatever files it finds in the way. Since git is mandatory, the changes will be left for you to review.

Review the changes

I repeat, the changes will be left for you to review. Don't just add them blindly, because some of your modifications can and will be overwritten.

If you need some help with undoing some of these changes, I recommend using a graphical interface.

Setting up your package

There are various steps to setting up your package on GitHub. Some are important now, and some will be relevant when you try to make your first release.

Add to GitHub

If you haven't yet, create a repo on GitHub and push your code to it.

Info

The actions will run and you will see errors in the documentation and linting. Do not despair.

Documentation

Go to your package setting on Github and find the "Actions" tab, the "General" link. On that page, find the "Workflow permissions" and change the selection to "Read and write permissions", and enable "Allow GitHub Actions can create and approve pull requests". This will allow the documentation workflow to work for development.

Go to the Actions page, click the failing Docs workflow and click on "re-run all jobs". It should pass now.

Now, go to your package setting on GitHub and find the "Pages" link. You should see an option to set the Source to "Deploy from a branch", and select the branch to be "gh-pages" and to deploy from the "/ (root)".

After circa 1 minute, you can check that the documentation was built properly.

Info

At this point, you should have passing workflows.

  1. Tests should have been passing from the start.
  2. Lint was fixed when we pushed the code to GitHub.
  3. Docs was fixed with the permissions change.

Documentation for releases

Info

This section is only relevant when making your first release, but it might be better to get it out of the way now.

You need to set a DOCUMENTER_KEY to build the documentation from the tags automatically when using TagBot (which we do by default). Do the following:

pkg> activate --temp
+git commit -m "Apply BestieTemplate vx.y.z"

Push your code to GitHub and head to Setting up your package for information on what to do next.

Now, go to Setting up your package to check what you still need to configure for your package.

Updating

To update the package, simply call

julia> BestieTemplate.update()

You will be asked the relevant questions of the package as if you had applied it. The big differences are:

Change previous answers

You can change your previous answers. In other words, if you though something was not mature enough in the past, but you are more confident in that now, you can adopt it now. This works even if the template was not updated itself.

As with the first application, you need to run pre-commit run -a to fix the unavoidable linting and formatting issues. Check the modifications in the relevant linter and formatting files, if you changed them manually, before doing it, though.

pre-commit run -a

You will possibly have conflicts when you apply the template - i.e., updates to the template that conflicts with changes that you've made to the package. Whenever a conflict appears, you will need to decide on whether to accept or reject the new changes. Fix the conflicts using git.

The underlying package copier will use git to apply the differences and it will overwrite whatever files it finds in the way. Since git is mandatory, the changes will be left for you to review.

Review the changes

I repeat, the changes will be left for you to review. Don't just add them blindly, because some of your modifications can and will be overwritten.

If you need some help with undoing some of these changes, I recommend using a graphical interface to git.

Setting up your package

There are various steps to setting up your package on GitHub. Some are important now, and some will be relevant when you try to make your first release.

Add to GitHub

If you haven't yet, create a repo on GitHub and push your code to it.

Info

The actions will run and you will see errors in the documentation and linting. Do not despair.

Documentation

Go to your package setting on Github and find the "Actions" tab, the "General" link. On that page, find the "Workflow permissions" and change the selection to "Read and write permissions", and enable "Allow GitHub Actions can create and approve pull requests". This will allow the documentation workflow to work for development.

Go to the Actions page, click the failing Docs workflow and click on "re-run all jobs". It should pass now.

Now, go to your package setting on GitHub and find the "Pages" link. You should see an option to set the Source to "Deploy from a branch", and select the branch to be "gh-pages" and to deploy from the "/ (root)".

After circa 1 minute, you can check that the documentation was built properly.

Info

At this point, you should have passing workflows.

  1. Tests should have been passing from the start.
  2. Lint was fixed when we pushed the code to GitHub.
  3. Docs was fixed with the permissions change.

Documentation for releases

Info

This section is only relevant when making your first release, but it might be better to get it out of the way now.

You need to set a DOCUMENTER_KEY to build the documentation from the tags automatically when using TagBot (which we do by default). Do the following:

pkg> activate --temp
 pkg> add DocumenterTools
 julia> using DocumenterTools
-julia> DocumenterTools.genkeys(user="UserName", repo="PackageName.jl")

Follow the instruction in the terminal.

Enable Codecov for code coverage

If you don't have a Codecov account, go to https://codecov.io and create one now. After creating an account and logging in, you will see your main page with a list of your packages. Select the one that you are creating, it will open a configuration page.

On the configuration page, select "Using GitHub Actions" as your CI. The first step in the list given you the CODECOV_TOKEN. Click on the "repository secret" link on that page. It should lead you to the GitHub settings > secrets and variables > actions, under a "New secret" screen. Write CODECOV_TOKEN on the "Name" field and paste the token that you see on codecov on the "Secret" field. Click "Add secret".

Step 2 is not necessary because it is already present in the template.

The next time that the tests are run, the coverage page will be updated, and the badge will be fixed.

Add key for Copier.yml workflow

Copier.yml is work in progress

This option is not selected by default because it is a work in progress. If you want to use it, you have to pass the key "AddCopierCI" => true to the data argument of generate or apply, or select "Ask me" when deciding how to answer the optional questions.

You can reapply the template in the future. This is normally a manual job, specially because normally there are conflicts. That being said, we are experimenting with having a workflow that automatically checks whether there are updates to the template and reapplies it. A Pull Request is created with the result.

Warning

This is optional, and in development, so you might want to delete the workflow instead.

If you decide to use, here are the steps to set it up:

  1. Create a Personal Access Token to be used by the Copier workflow.
  2. Go to https://github.com/settings/tokens.
  3. Create a token with "Content", "Pull-request", and "Workflows" permissions.
  4. Copy the Token.
  5. Go to your YOUR_PACKAGE_URL/settings/secrets/actions.
  6. Create a "New repository secret" named COPIER_PAT.

CITATION.cff and Zenodo deposition

Update your CITATION.cff file with correct information. You can use cffinit to generate it easily.

Before releasing, enable Zenodo integration at https://zenodo.org/account/settings/github/ to automatically generate a deposition of your package, i.e., archive a version on Zenodo and generate a DOI.

Update README.md

  1. Update the badges
  2. Add a description

Enable discussions

Enable GitHub discussions.

First release

When you are ready to make your first release, enable the Julia Registrator bot. Make sure that you haven't skipped these sections:

+julia> DocumenterTools.genkeys(user="UserName", repo="PackageName.jl")

Follow the instruction in the terminal.

Enable Codecov for code coverage

If you don't have a Codecov account, go to https://codecov.io and create one now. After creating an account and logging in, you will see your main page with a list of your packages. Select the one that you are creating, it will open a configuration page.

On the configuration page, select "Using GitHub Actions" as your CI. The first step in the list given you the CODECOV_TOKEN. Click on the "repository secret" link on that page. It should lead you to the GitHub settings > secrets and variables > actions, under a "New secret" screen. Write CODECOV_TOKEN on the "Name" field and paste the token that you see on codecov on the "Secret" field. Click "Add secret".

Step 2 is not necessary because it is already present in the template.

The next time that the tests are run, the coverage page will be updated, and the badge will be fixed.

Add key for Copier.yml workflow

Copier.yml is work in progress

This option is not selected by default because it is a work in progress. If you want to use it, you have to pass the key "AddCopierCI" => true to the data argument of generate or apply, or select "Ask me" when deciding how to answer the optional questions.

You can reapply the template in the future. This is normally a manual job, specially because normally there are conflicts. That being said, we are experimenting with having a workflow that automatically checks whether there are updates to the template and reapplies it. A Pull Request is created with the result.

Warning

This is optional, and in development, so you might want to delete the workflow instead.

If you decide to use, here are the steps to set it up:

  1. Create a Personal Access Token to be used by the Copier workflow.
  2. Go to https://github.com/settings/tokens.
  3. Create a token with "Content", "Pull-request", and "Workflows" permissions.
  4. Copy the Token.
  5. Go to your YOUR_PACKAGE_URL/settings/secrets/actions.
  6. Create a "New repository secret" named COPIER_PAT.

CITATION.cff and Zenodo deposition

Update your CITATION.cff file with correct information. You can use cffinit to generate it easily.

Before releasing, enable Zenodo integration at https://zenodo.org/account/settings/github/ to automatically generate a deposition of your package, i.e., archive a version on Zenodo and generate a DOI.

Update README.md

  1. Update the badges
  2. Add a description

Enable discussions

Enable GitHub discussions.

First release

When you are ready to make your first release, enable the Julia Registrator bot. Make sure that you haven't skipped these sections:

diff --git a/dev/20-explanation/index.html b/dev/20-explanation/index.html index 3ae9cc8..83b048a 100644 --- a/dev/20-explanation/index.html +++ b/dev/20-explanation/index.html @@ -1,2 +1,2 @@ -Explanation · BestieTemplate.jl

Explanation

In this section, we hope to explain the motivation for the package, and what is inside the template. Some things might have been obvious when creating the package and not at the moment, so feel free to create issues to ask, or suggest, clarifications.

You can see all questions in details in the Questions page.

Tip

If something is missing or not explained enough, please open an issue.

The engine, the project generator, and the template

Let me start by marking some names clearer.

  • The template is the collection of files and folders written with some placeholders. For instance, the link to a GitHub project will be something like https://github.com/{{ PackageOwner }}/{{ PackageName }}.jl.
  • The engine is the tool that converts the template into the end result, by changing the placeholders into the actual values that we want.
  • The project generator is the tool that interacts with the user to get the placeholder values and give to the engine.

Comparison with existing solutions

Julia has a very good package generator called PkgTemplates.jl, so why did we create another one?

The short answer is that we want a more streamlined development experience, a template more focused on best practices, and the ability to keep reusing the template whenever new tools and ideas are implemented.

In more details, first, see the differences in the parts of the project in the table below:

BestieTemplate.jlPkgTemplates.jl
TemplatePart of the packagePart of the package
EngineJinjaMustache
Project generatorcopier, with some wrappers in the packagePart of the package

Now, we can split this into three comparisons.

Template differences

The template differences are mostly due to opinion and contributions and it should be easy to translate files from one template to the other. We are heavily inspired by PkgTemplates.jl, as we used it for many years, but we made some changes in the hopes of improving software sustainability, package maintainability and code quality (which we just overtly simplify as best practices). As such, our current differences (as of the time of writing) are:

  • We have more best practices tools, such as pre-commit, configuration for linters and formatters for Julia, Markdown, TOML, YAML and JSON, CITATION.cff, Lint GitHub workflow, .editorconfig file, issues and pull requests templates, etc.
  • We focus on the main use cases (GitHub and GitHub actions), so we have much less options.

Engine differences

We can't say much about these, since we don't know or care in details.

Project generator differences

PkgTemplates.jl is a project generator. This means that if you want to programmatically create templates inside Julia, this is the best solution. The questions (user interface) are implemented by the package, which then translates that into the answers for the engine. Disclaimer: We haven't worked on the package, this information is based on the docs.

We use copier as project generator. It is an external Python tool, so we also include some wrappers in the package to use it from Julia without the need to explicitly install it. Copier has many features, so we recommend that you check their comparisons pages for more information.

Most notably, the feature that made us choose copier in the first place has the ability to applied and reapplied to existing projects. This means that existing packages can benefit from all best practices that we provide. Furthermore, they can keep reaping benefits when we create new versions of the template.

Template details

Let's dive into the details of the template now.

The template contains a few required questions and then asks you whether you would like to use

  • The "recommended" options, which include our current recommendation for best practices;
  • The "minimum" options, which answers "no" to everything, but still leaves you with a decent package to start; or
  • The option to answer every optional question individually.

The motivation behind "minimum" vs "recommended" is:

The "minimum" option includes all the Julia package basic plus a few things we think are of interest to all use cases of package development. Normal use cases for the "minimum" option are:

  • You are testing the template;
  • You are developing solo and wants to "move fast and break things";
  • Your package is in very early stage.
  • You are installing the "minimum" before installing the "recommended" to decrease the PR size.

Our loose criteria to make something part of the minimum is (exceptions may apply):

  • It is not too intrusive to development (e.g., .editorconfig);
  • It is a very common practice or tool (e.g., TagBot.yml and CompatHelper.yml);
  • It is a very strong recommendation that we think you should adopt (e.g., docs).

The "recommended" option includes all the minimum things plus things that we believe will improve quality and sustainability of packages. Normal use cases for the "recommended" option are:

  • You have a large package or a collection of packages;
  • You are not developing the package alone;
  • You expect open source contributions;
  • You agree with the best practices.

Our loose criteria to make something part of the recommended, but not minimum, is (exceptions may apply):

  • Despite being good, it requires change of behaviour (e.g., pre-commit);
  • It does not make sense for solo devs (e.g., all-contributors);
  • It creates friction - which is good to ensure quality but slows developement (e.g., issue templates).

Finally, there are other optional features. These are neither recommended nor part of the minimum template, which means that unless you (know and) set them explicitly, you are not using them.

The loose criteria to make something not recommended, nor minimum, is:

  • It is a best practice, but for a niche audience (e.g., .cirrus.yml for testing on FreeBSD);

To see all the questions, head to Questions.

Basic package structure

This is the basic structure of a package:

  • PackageName.jl/
    • src/
      • PackageName.jl
    • test/
      • Project.toml
      • runtests.jl
    • LICENSE.md
    • Project.toml
    • README.md

With the exception of test/Project.toml, all other files are requirements to register a package.

Documentation

On top of the basic structure, we add some Documenter.jl structure.

  • docs/
    • src/
      • 90-contributing.md
      • 91-developer.md
      • 95-reference.md
      • index.md
    • make.jl
    • Project.toml

Brief explanation of the details:

  • The Project.toml, make.jl and src/index.md are the basic structure.
  • docs/src/90-contributing.md: Sometimes added as CONTRIBUTING.md, it explains how contributors can get involved in the project.
  • docs/src/91-developer.md: Sometimes added as README.dev.md or DEVELOPER.md, it explains how to setup your local environment and other information relevant for developers only.
  • docs/src/95-reference.md is the API reference page, which include an @autodocs.

One noteworthy aspect of our make.jl, is that we include some code to automatically generate the list of pages. Create a file in the form ##-name.md, where ## is a two-digit number, and it will be automatically added to the pages list.

index.md

You might have noticed that index.md is not numbered, and that is because Documenter.jl checks for that files specifically to define the landing page. Instead, we explicitly add "Home" => "index." to make.jl.

Linting and Formatting

The most important file related to linting and formatting is .pre-commit-config.yaml, which is the configuration for pre-commit. It defines a list of linters and formatters for Julia, Markdown, TOML, YAML, and JSON.

It requires installing pre-commit (I recommend installing it globally with pipx). Installing pre-commit (pre-commit install) will make sure that it runs the relevant hooks before committing. Furthermore, if you run pre-commit run -a, it runs all hooks.

Some hooks in the .pre-commit-config.yaml file have configuration files of their own: .JuliaFormatter.toml, .markdownlint.json, .lychee.toml, and .yamllint.yml.

Also slightly related, is the .editorconfig file, which tells your editor, if you install the correct plugin, how to format some things.

GitHub Workflows

We have a few workflows, with plans to expand in the future:

  • CompatHelper.yml: Should be well known by now. It checks that your Project.toml compat entries are up-to-date.
  • Copier.yml: This will periodically check the template for updates. If there are updates, this action creates a pull request updating your repo.
  • Docs.yml: Build the docs. Only runs when relevant files change.
  • Lint.yml: Run the linter and formatter through the command pre-commit run -a.
  • TagBot.yml: Create GitHub releases automatically after your new release is merged on the Registry.
  • For testing, we have
    • ReusableTest.yml: Defines a reusable workflow with the testing.
    • Test.yml: Defines a matrix of tests to be run whenever main is updated or a tag is created. Uses the ReusableTest workflow. If "Simplified PR Test" was not chosen, then this also runs when there are pull requests.
    • TestOnPRs.yml: Defines a test to be run when pull requests are created. Only the latest stable Julia version is tested on a ubuntu-latest image. Uses the ReusableTest workflow. If "Simplified PR Test" was not chosen, then this file does not exist.

Issues and PR templates

We include issues and PR templates for GitHub (see .github/). These provide a starting point to your project management.

Other files

  • .cirrus.yml: For Cirrus CI, which we use solely for FreeBSD testing.
  • CITATION.cff: Instead of the more classic .bib, we use .cff, which serves a better purpose of providing the metadata of the package. CFF files have been adopted by GitHub, so you can generate a BibTeX entry by clicking on "Cite this repository" on the repository's main page. CFF files have also been adopted by Zenodo to provide the metadata of your deposition.
  • CODE_OF_CONDUCT.md: A code of conduct file from Contributor Covenant.
+Explanation · BestieTemplate.jl

Explanation

In this section, we hope to explain the motivation for the package, and what is inside the template. Some things might have been obvious when creating the package and not at the moment, so feel free to create issues to ask, or suggest, clarifications.

You can see all questions in details in the Questions page.

Tip

If something is missing or not explained enough, please open an issue.

The engine, the project generator, and the template

Let me start by marking some names clearer.

  • The template is the collection of files and folders written with some placeholders. For instance, the link to a GitHub project will be something like https://github.com/{{ PackageOwner }}/{{ PackageName }}.jl.
  • The engine is the tool that converts the template into the end result, by changing the placeholders into the actual values that we want.
  • The project generator is the tool that interacts with the user to get the placeholder values and give to the engine.

Comparison with existing solutions

Julia has a very good package generator called PkgTemplates.jl, so why did we create another one?

The short answer is that we want a more streamlined development experience, a template more focused on best practices, and the ability to keep reusing the template whenever new tools and ideas are implemented.

In more details, first, see the differences in the parts of the project in the table below:

BestieTemplate.jlPkgTemplates.jl
TemplatePart of the packagePart of the package
EngineJinjaMustache
Project generatorcopier, with some wrappers in the packagePart of the package

Now, we can split this into three comparisons.

Template differences

The template differences are mostly due to opinion and contributions and it should be easy to translate files from one template to the other. We are heavily inspired by PkgTemplates.jl, as we used it for many years, but we made some changes in the hopes of improving software sustainability, package maintainability and code quality (which we just overtly simplify as best practices). As such, our current differences (as of the time of writing) are:

  • We have more best practices tools, such as pre-commit, configuration for linters and formatters for Julia, Markdown, TOML, YAML and JSON, CITATION.cff, Lint GitHub workflow, .editorconfig file, issues and pull requests templates, etc.
  • We focus on the main use cases (GitHub and GitHub actions), so we have much less options.

Engine differences

We can't say much about these, since we don't know or care in details.

Project generator differences

PkgTemplates.jl is a project generator. This means that if you want to programmatically create templates inside Julia, this is the best solution. The questions (user interface) are implemented by the package, which then translates that into the answers for the engine. Disclaimer: We haven't worked on the package, this information is based on the docs.

We use copier as project generator. It is an external Python tool, so we also include some wrappers in the package to use it from Julia without the need to explicitly install it. Copier has many features, so we recommend that you check their comparisons pages for more information.

Most notably, the feature that made us choose copier in the first place has the ability to applied and reapplied to existing projects. This means that existing packages can benefit from all best practices that we provide. Furthermore, they can keep reaping benefits when we create new versions of the template.

Template details

Let's dive into the details of the template now.

The template contains a few required questions and then asks you whether you would like to use

  • The "recommended" options, which include our current recommendation for best practices;
  • The "minimum" options, which answers "no" to everything, but still leaves you with a decent package to start; or
  • The option to answer every optional question individually.

The motivation behind "minimum" vs "recommended" is:

The "minimum" option includes all the Julia package basic plus a few things we think are of interest to all use cases of package development. Normal use cases for the "minimum" option are:

  • You are testing the template;
  • You are developing solo and wants to "move fast and break things";
  • Your package is in very early stage.
  • You are installing the "minimum" before installing the "recommended" to decrease the PR size.

Our loose criteria to make something part of the minimum is (exceptions may apply):

  • It is not too intrusive to development (e.g., .editorconfig);
  • It is a very common practice or tool (e.g., TagBot.yml and CompatHelper.yml);
  • It is a very strong recommendation that we think you should adopt (e.g., docs).

The "recommended" option includes all the minimum things plus things that we believe will improve quality and sustainability of packages. Normal use cases for the "recommended" option are:

  • You have a large package or a collection of packages;
  • You are not developing the package alone;
  • You expect open source contributions;
  • You agree with the best practices.

Our loose criteria to make something part of the recommended, but not minimum, is (exceptions may apply):

  • Despite being good, it requires change of behaviour (e.g., pre-commit);
  • It does not make sense for solo devs (e.g., all-contributors);
  • It creates friction - which is good to ensure quality but slows developement (e.g., issue templates).

Finally, there are other optional features. These are neither recommended nor part of the minimum template, which means that unless you (know and) set them explicitly, you are not using them.

The loose criteria to make something not recommended, nor minimum, is:

  • It is a best practice, but for a niche audience (e.g., .cirrus.yml for testing on FreeBSD);

To see all the questions, head to Questions.

Basic package structure

This is the basic structure of a package:

  • PackageName.jl/
    • src/
      • PackageName.jl
    • test/
      • Project.toml
      • runtests.jl
    • LICENSE.md
    • Project.toml
    • README.md

With the exception of test/Project.toml, all other files are requirements to register a package.

Documentation

On top of the basic structure, we add some Documenter.jl structure.

  • docs/
    • src/
      • 90-contributing.md
      • 91-developer.md
      • 95-reference.md
      • index.md
    • make.jl
    • Project.toml

Brief explanation of the details:

  • The Project.toml, make.jl and src/index.md are the basic structure.
  • docs/src/90-contributing.md: Sometimes added as CONTRIBUTING.md, it explains how contributors can get involved in the project.
  • docs/src/91-developer.md: Sometimes added as README.dev.md or DEVELOPER.md, it explains how to setup your local environment and other information relevant for developers only.
  • docs/src/95-reference.md is the API reference page, which include an @autodocs.

One noteworthy aspect of our make.jl, is that we include some code to automatically generate the list of pages. Create a file in the form ##-name.md, where ## is a two-digit number, and it will be automatically added to the pages list.

index.md

You might have noticed that index.md is not numbered, and that is because Documenter.jl checks for that files specifically to define the landing page. Instead, we explicitly add "Home" => "index." to make.jl.

Linting and Formatting

The most important file related to linting and formatting is .pre-commit-config.yaml, which is the configuration for pre-commit. It defines a list of linters and formatters for Julia, Markdown, TOML, YAML, and JSON.

It requires installing pre-commit (I recommend installing it globally with pipx). Installing pre-commit (pre-commit install) will make sure that it runs the relevant hooks before committing. Furthermore, if you run pre-commit run -a, it runs all hooks.

Some hooks in the .pre-commit-config.yaml file have configuration files of their own: .JuliaFormatter.toml, .markdownlint.json, .lychee.toml, and .yamllint.yml.

Also slightly related, is the .editorconfig file, which tells your editor, if you install the correct plugin, how to format some things.

GitHub Workflows

We have a few workflows, with plans to expand in the future:

  • CompatHelper.yml: Should be well known by now. It checks that your Project.toml compat entries are up-to-date.
  • Copier.yml: This will periodically check the template for updates. If there are updates, this action creates a pull request updating your repo.
  • Docs.yml: Build the docs. Only runs when relevant files change.
  • Lint.yml: Run the linter and formatter through the command pre-commit run -a.
  • TagBot.yml: Create GitHub releases automatically after your new release is merged on the Registry.
  • For testing, we have
    • ReusableTest.yml: Defines a reusable workflow with the testing.
    • Test.yml: Defines a matrix of tests to be run whenever main is updated or a tag is created. Uses the ReusableTest workflow. If "Simplified PR Test" was not chosen, then this also runs when there are pull requests.
    • TestOnPRs.yml: Defines a test to be run when pull requests are created. Only the latest stable Julia version is tested on a ubuntu-latest image. Uses the ReusableTest workflow. If "Simplified PR Test" was not chosen, then this file does not exist.

Issues and PR templates

We include issues and PR templates for GitHub (see .github/). These provide a starting point to your project management.

Other files

  • .cirrus.yml: For Cirrus CI, which we use solely for FreeBSD testing.
  • CITATION.cff: Instead of the more classic .bib, we use .cff, which serves a better purpose of providing the metadata of the package. CFF files have been adopted by GitHub, so you can generate a BibTeX entry by clicking on "Cite this repository" on the repository's main page. CFF files have also been adopted by Zenodo to provide the metadata of your deposition.
  • CODE_OF_CONDUCT.md: A code of conduct file from Contributor Covenant.
diff --git a/dev/30-questions/index.html b/dev/30-questions/index.html index f333b3d..e73b909 100644 --- a/dev/30-questions/index.html +++ b/dev/30-questions/index.html @@ -14,9 +14,9 @@ print(read("MyPkg/Project.toml", String))
/home/runner/work/BestieTemplate.jl/BestieTemplate.jl/docs/.CondaPkg/env/lib/python3.11/site-packages/copier/vcs.py:175: ShallowCloneWarning: The repository '/home/runner/work/BestieTemplate.jl/BestieTemplate.jl' is a shallow clone, this might lead to unexpected failure or unusually high resource consumption.
   warn(
 name = "NotMyPkg"
-uuid = "63bfeb13-f38b-5df4-a601-f23981cb5c89"
+uuid = "aaa89687-7a30-56fa-a0fb-6b6d81205fd3"
 authors = ["Bestie"]
 version = "0.1.0"
 
 [compat]
-julia = "1.6"
Help wanted

We have not managed to create a table of contents because we can't create the anchors in the headers. If you have an idea of what to do, help is appreciated.

Section: Essential

PackageName

Question (in the CLI): Package name (without '.jl')

Description:

The package name. Must start with a capital letter, and be comprised of letters and numbers.

Required.

For new packages, it will be inferred from the path, the first argument of generate.

For existing packages, it will be inferred from the Project.toml name field.

PackageUUID

Question (in the CLI): UUID (For existing packages, copy the UUID from Project.toml, otherwise use the one generated below)

Description:

The unique identifier of the package.

Required.

Defaults to randomly generated UUID.

For existing packages, it will be inferred from the Project.toml uuid field.

PackageOwner

Question (in the CLI): GitHub username or organization that owns the package (This will be used for URLs)

Description:

The owner of the package repo, i.e., the user or organization in the package URL.

This assumes that GitHub is being used, which, at the moment, is the only possibility.

Does not have a default.

For existing packages, it will be inferred from the repo information in the docs/make.jl file.

AuthorName

Question (in the CLI): (Deprecated in 0.10.0) Name of the package author (Used to kickstart a few files)

Description:

!!! warning Deprecated

AuthorName has been replaced by Authors.

Defines the name of the author.

AuthorEmail

Question (in the CLI): (Deprecated in 0.10.0) E-mail of the package author (Used to kickstart a few files)

Description:

!!! warning Deprecated

AuthorEmail has been replaced by Authors.

Defines the e-mail of the author.

Authors

Question (in the CLI): Package authors separated by commas (We recommend the form NAME <EMAIL>, but this can be ignored)

Description:

The authors of the package in a single line, separated by commas. The actual content is not verified.

We recommend using the format NAME <EMAIL> for each author, so that it is consistent with most uses of author. However, that is not necessary.

If you follow the recommended format, there are better defaults in other places.

Another common alternative is to list the main author and add and contributors. This is also completely valid.

Can't be empty.

Required. No default.

For existing packages, it will be inferred from the authors information in the Project.toml.

LicenseCopyrightHolders

Question (in the CLI): License Copyright Holders (Added in front of "Copyright (c) " notices, when applicable)

Description:

Some license files include a "Copyright (c) <LicenseCopyrightHolders>" notice.

Defaults to names in the Authors question, if they follow the recommended format.

For instance, if the Authors field is "NAME1 <EMAIL1>,NAME2 <EMAIL2>", this will default to "NAME1, NAME2".

Indentation

Question (in the CLI): Indentation length (Used in .JuliaFormatter and other configuration files of formatters and linters if you add them)

Description:

The number of spaces that define an indentation level.

This is used in many configuration files:

This does NOT enforce indentation by itself, you still need tools to indent these.

pre-commit is the recommended way to run these tools.

For existing packages, this will be inferred from the indent value in the .JuliaFormatter.toml file.

License

Question (in the CLI): Package license (You need an OSI license to register. You can suggest new licenses in the issues)

Description:

Multiple choice question to select a License.

Defaults to the MIT License, which is the most common choice for Julia packages.

JuliaMinVersion

Question (in the CLI): Minimum Julia version (Used in Project.toml. The suggestion below is the LTS version)

Description:

Minimum compat Julia version. This will be used in the Project.toml and as a suggestion for the minimum Julia version in the CI, which is another question.

Defaults to the LTS version.

For existing packages, it will be inferred from the compat section in the Project.toml files.

Section: Strategy

AnswerStrategy

Question (in the CLI): Strategy for optional questions (You can see the full list of questions in https://abelsiqueira.com/BestieTemplate.jl/dev/30-questions/)

Description:

This defines how to deal with the rest of the questions.

The minimum strategy answers "no" to every question. This is not the same as a bare-bones package. The resulting package will have the minimum amount of best practices that we recommend.

The recommended strategy uses all our recommended best practices, which might be overwhelming for anyone. See the answers below this step to see all the options. This is not the same as saying "yes" to everything.

The ask strategy does not select anything from the list below. All questions will be asked.

Notice that some options are only available through the ask strategy, or by explicitly passing them to the Bestie command.

Defaults to the "recommended" strategy.

Section: Code Quality

AddPrecommit

Question (in the CLI): Pre-commit (Whether to add pre-commit.org. It runs before every commit fixing your formatting and preventing bad practices)

Description:

Pre-commit runs several "hooks" whenever you make a commit. These hooks mostly fall into these categories:

Many pre-commit hooks are also available as editor plugins, and could be run continually in your editor, although we don't have a list for that (yet).

Defaults to yes for the recommended strategy, or no otherwise.

AutoIncludeTests

Question (in the CLI): Auto-include test files named test-<name>.jl (Incentivizes splitting your tests and better naming them, and helps avoiding forgetting to include the tests manually)

Description:

This write a runtests.jl file that automatically recursively includes all test-*.jl files in the test folder inside @testsets.

This incentivizes separating the tests and makes sure that you don't forget to include them.

Defaults to yes for the recommended strategy, or no otherwise.

Section: Continuous Integration

UseCirrusCI

Question (in the CLI): FreeBSD CI test with CirrusCI (Add CirrusCI to run the package tests on FreeBSD?)

Description:

Controls whether to add a .cirrus.yml to run tests on the Cirrus CI platform for the FreeBSD Operating System.

Defaults to no.

AddMacToCI

Question (in the CLI): MacOS CI test (Package tests run on Ubuntu latest. Do you want to add macOS latest as well?)

Description:

Controls whether macos-latest is added to list of OSs being tested in the Test workflow.

Defaults to yes for the recommended strategy, or no otherwise.

AddWinToCI

Question (in the CLI): Windows CI test (Same as above, but for Windows)

Description:

Controls whether windows-latest is added to list of OSs being tested in the Test workflow.

Defaults to yes for the recommended strategy, or no otherwise.

JuliaMinCIVersion

Question (in the CLI): Minimum Julia version used in the tests (min, lts, or a version. See https://github.com/julia-actions/setup-julia#examples for accepted values)

Description:

The Test workflow runs two versions of Julia by default: the latest stable release, which is defined by "1", and this version.

It defaults to either "lts", or the version that you answered in JuliaMinVersion, if it wasn't the LTS.

Also accepts "min", which defaults to the minimum supported version in the compat section of Project.toml, or a version specification. See https://github.com/julia-actions/setup-julia#examples for more options.

RunJuliaNightlyOnCI

Question (in the CLI): Julia nightly CI test (Package tests run on Julia version {{ JuliaMinVersion }} and on the latest stable release. Do you also want to run them on the nightly version?)

Description:

Controls whether the nightly version of Julia is added to the list of Julia versions being tested in the Test workflow.

Defaults to no.

AddCopierCI

Question (in the CLI): Copier.yml (Add workflow to check for template updates? This is a work in progress workflow that checks whether there has been an update to the template and automatically create a pull request)

Description:

!!! warning Highly experimental

This feature is highly experimental and can be removed without a deprecation period.

Controls whether to add a workflow to check for updates in the template and create a PR applying them.

Defaults to yes for the recommended strategy, or no otherwise.

Section: Community

AddGitHubTemplates

Question (in the CLI): GitHub issue templates (Add forms for issue creation to improve the description quality)

Description:

Whether to add GitHub issue templates files. These files become forms when an user wants to create an issue on GitHub. They are useful for separating the kind of questions the user needs to fill and the automatic label added to the created issue.

Defaults to yes for the recommended strategy, or no otherwise.

AddContributionDocs

Question (in the CLI): Add documentation files on how to contribute to the project (90-contributing.md will give general guidelines, and 91-developer.md will give practical information)

Description:

There are two files for contributors:

Some projects will add files like CONTRIBUTING.md and README.dev.md with this information, or just paste everything in the README.md. We choose to have this information as part of the Julia docs, to focus information in a single source (documentation pages).

Defaults to yes for the recommended strategy, or no otherwise.

AddAllcontributors

Question (in the CLI): Add allcontributors (allcontributors.org is a project that adds collaborators information in the README and the docs)

Description:

To make it easy to recognize contributions of every kind, we recommend using allcontributors.

The proposed workflow with allcontributors is to add a comment like "@allcontributors, please add @username for <type>" in a PR or issue. The bot will create a PR adding the information to the relevant places (README.md and docs/src/index.md).

Defaults to yes for the recommended strategy, or no otherwise.

AddCodeOfConduct

Question (in the CLI): Code of conduct file (Add a CODEOFCONDUCT.md file from Contributor Covenant?)

Description:

This uses version 2.1 of the Contributor Covenant code of conduct.

Defaults to yes for the recommended strategy, or no otherwise.

CodeOfConductContact

Question (in the CLI): Contact person/entity listed in the CODEOFCONDUCT.md file (Will be listed as contact to enforce the code of conduct, if necessary)

Description:

This is the contact person or entity for enforcement of the code of conduct. It will be added to the CODEOFCONDUCT file, in a section titled "Enforcement".

Defaults to the first authors' e-mail using a Regex substitution from the Authors question.

+julia = "1.6"
Help wanted

We have not managed to create a table of contents because we can't create the anchors in the headers. If you have an idea of what to do, help is appreciated.

Section: Essential

PackageName

Question (in the CLI): Package name (without '.jl')

Description:

The package name. Must start with a capital letter, and be comprised of letters and numbers.

Required.

For new packages, it will be inferred from the path, the first argument of generate.

For existing packages, it will be inferred from the Project.toml name field.

PackageUUID

Question (in the CLI): UUID (For existing packages, copy the UUID from Project.toml, otherwise use the one generated below)

Description:

The unique identifier of the package.

Required.

Defaults to randomly generated UUID.

For existing packages, it will be inferred from the Project.toml uuid field.

PackageOwner

Question (in the CLI): GitHub username or organization that owns the package (This will be used for URLs)

Description:

The owner of the package repo, i.e., the user or organization in the package URL.

This assumes that GitHub is being used, which, at the moment, is the only possibility.

Does not have a default.

For existing packages, it will be inferred from the repo information in the docs/make.jl file.

AuthorName

Question (in the CLI): (Deprecated in 0.10.0) Name of the package author (Used to kickstart a few files)

Description:

!!! warning Deprecated

AuthorName has been replaced by Authors.

Defines the name of the author.

AuthorEmail

Question (in the CLI): (Deprecated in 0.10.0) E-mail of the package author (Used to kickstart a few files)

Description:

!!! warning Deprecated

AuthorEmail has been replaced by Authors.

Defines the e-mail of the author.

Authors

Question (in the CLI): Package authors separated by commas (We recommend the form NAME <EMAIL>, but this can be ignored)

Description:

The authors of the package in a single line, separated by commas. The actual content is not verified.

We recommend using the format NAME <EMAIL> for each author, so that it is consistent with most uses of author. However, that is not necessary.

If you follow the recommended format, there are better defaults in other places.

Another common alternative is to list the main author and add and contributors. This is also completely valid.

Can't be empty.

Required. No default.

For existing packages, it will be inferred from the authors information in the Project.toml.

LicenseCopyrightHolders

Question (in the CLI): License Copyright Holders (Added in front of "Copyright (c) " notices, when applicable)

Description:

Some license files include a "Copyright (c) <LicenseCopyrightHolders>" notice.

Defaults to names in the Authors question, if they follow the recommended format.

For instance, if the Authors field is "NAME1 <EMAIL1>,NAME2 <EMAIL2>", this will default to "NAME1, NAME2".

Indentation

Question (in the CLI): Indentation length (Used in .JuliaFormatter and other configuration files of formatters and linters if you add them)

Description:

The number of spaces that define an indentation level.

This is used in many configuration files:

This does NOT enforce indentation by itself, you still need tools to indent these.

pre-commit is the recommended way to run these tools.

For existing packages, this will be inferred from the indent value in the .JuliaFormatter.toml file.

License

Question (in the CLI): Package license (You need an OSI license to register. You can suggest new licenses in the issues)

Description:

Multiple choice question to select a License.

Defaults to the MIT License, which is the most common choice for Julia packages.

JuliaMinVersion

Question (in the CLI): Minimum Julia version (Used in Project.toml. The suggestion below is the LTS version)

Description:

Minimum compat Julia version. This will be used in the Project.toml and as a suggestion for the minimum Julia version in the CI, which is another question.

Defaults to the LTS version.

For existing packages, it will be inferred from the compat section in the Project.toml files.

Section: Strategy

AnswerStrategy

Question (in the CLI): Strategy for optional questions (You can see the full list of questions in https://abelsiqueira.com/BestieTemplate.jl/dev/30-questions/)

Description:

This defines how to deal with the rest of the questions.

The minimum strategy answers "no" to every question. This is not the same as a bare-bones package. The resulting package will have the minimum amount of best practices that we recommend.

The recommended strategy uses all our recommended best practices, which might be overwhelming for anyone. See the answers below this step to see all the options. This is not the same as saying "yes" to everything.

The ask strategy does not select anything from the list below. All questions will be asked.

Notice that some options are only available through the ask strategy, or by explicitly passing them to the Bestie command.

Defaults to the "recommended" strategy.

Section: Code Quality

AddPrecommit

Question (in the CLI): Pre-commit (Whether to add pre-commit.org. It runs before every commit fixing your formatting and preventing bad practices)

Description:

Pre-commit runs several "hooks" whenever you make a commit. These hooks mostly fall into these categories:

Many pre-commit hooks are also available as editor plugins, and could be run continually in your editor, although we don't have a list for that (yet).

Defaults to yes for the recommended strategy, or no otherwise.

AutoIncludeTests

Question (in the CLI): Auto-include test files named test-<name>.jl (Incentivizes splitting your tests and better naming them, and helps avoiding forgetting to include the tests manually)

Description:

This write a runtests.jl file that automatically recursively includes all test-*.jl files in the test folder inside @testsets.

This incentivizes separating the tests and makes sure that you don't forget to include them.

Defaults to yes for the recommended strategy, or no otherwise.

Section: Continuous Integration

UseCirrusCI

Question (in the CLI): FreeBSD CI test with CirrusCI (Add CirrusCI to run the package tests on FreeBSD?)

Description:

Controls whether to add a .cirrus.yml to run tests on the Cirrus CI platform for the FreeBSD Operating System.

Defaults to no.

AddMacToCI

Question (in the CLI): MacOS CI test (Package tests run on Ubuntu latest. Do you want to add macOS latest as well?)

Description:

Controls whether macos-latest is added to list of OSs being tested in the Test workflow.

Defaults to yes for the recommended strategy, or no otherwise.

AddWinToCI

Question (in the CLI): Windows CI test (Same as above, but for Windows)

Description:

Controls whether windows-latest is added to list of OSs being tested in the Test workflow.

Defaults to yes for the recommended strategy, or no otherwise.

JuliaMinCIVersion

Question (in the CLI): Minimum Julia version used in the tests (min, lts, or a version. See https://github.com/julia-actions/setup-julia#examples for accepted values)

Description:

The Test workflow runs two versions of Julia by default: the latest stable release, which is defined by "1", and this version.

It defaults to either "lts", or the version that you answered in JuliaMinVersion, if it wasn't the LTS.

Also accepts "min", which defaults to the minimum supported version in the compat section of Project.toml, or a version specification. See https://github.com/julia-actions/setup-julia#examples for more options.

RunJuliaNightlyOnCI

Question (in the CLI): Julia nightly CI test (Package tests run on Julia version {{ JuliaMinVersion }} and on the latest stable release. Do you also want to run them on the nightly version?)

Description:

Controls whether the nightly version of Julia is added to the list of Julia versions being tested in the Test workflow.

Defaults to no.

AddCopierCI

Question (in the CLI): Copier.yml (Add workflow to check for template updates? This is a work in progress workflow that checks whether there has been an update to the template and automatically create a pull request)

Description:

!!! warning Highly experimental

This feature is highly experimental and can be removed without a deprecation period.

Controls whether to add a workflow to check for updates in the template and create a PR applying them.

Defaults to yes for the recommended strategy, or no otherwise.

Section: Community

AddGitHubTemplates

Question (in the CLI): GitHub issue templates (Add forms for issue creation to improve the description quality)

Description:

Whether to add GitHub issue templates files. These files become forms when an user wants to create an issue on GitHub. They are useful for separating the kind of questions the user needs to fill and the automatic label added to the created issue.

Defaults to yes for the recommended strategy, or no otherwise.

AddContributionDocs

Question (in the CLI): Add documentation files on how to contribute to the project (90-contributing.md will give general guidelines, and 91-developer.md will give practical information)

Description:

There are two files for contributors:

Some projects will add files like CONTRIBUTING.md and README.dev.md with this information, or just paste everything in the README.md. We choose to have this information as part of the Julia docs, to focus information in a single source (documentation pages).

Defaults to yes for the recommended strategy, or no otherwise.

AddAllcontributors

Question (in the CLI): Add allcontributors (allcontributors.org is a project that adds collaborators information in the README and the docs)

Description:

To make it easy to recognize contributions of every kind, we recommend using allcontributors.

The proposed workflow with allcontributors is to add a comment like "@allcontributors, please add @username for <type>" in a PR or issue. The bot will create a PR adding the information to the relevant places (README.md and docs/src/index.md).

Defaults to yes for the recommended strategy, or no otherwise.

AddCodeOfConduct

Question (in the CLI): Code of conduct file (Add a CODEOFCONDUCT.md file from Contributor Covenant?)

Description:

This uses version 2.1 of the Contributor Covenant code of conduct.

Defaults to yes for the recommended strategy, or no otherwise.

CodeOfConductContact

Question (in the CLI): Contact person/entity listed in the CODEOFCONDUCT.md file (Will be listed as contact to enforce the code of conduct, if necessary)

Description:

This is the contact person or entity for enforcement of the code of conduct. It will be added to the CODEOFCONDUCT file, in a section titled "Enforcement".

Defaults to the first authors' e-mail using a Regex substitution from the Authors question.

diff --git a/dev/90-contributing/index.html b/dev/90-contributing/index.html index a43e494..575c4ac 100644 --- a/dev/90-contributing/index.html +++ b/dev/90-contributing/index.html @@ -1,2 +1,2 @@ -Contributing guidelines · BestieTemplate.jl

Contributing guidelines

First of all, thanks for the interest!

We welcome all kinds of contribution, including, but not limited to code, documentation, examples, configuration, issue creating, etc.

Be polite and respectful, and follow the code of conduct.

Bug reports and discussions

If you think you found a bug, feel free to open an issue. Focused suggestions and requests can also be opened as issues. Before opening a pull request, start an issue or a discussion on the topic, please.

Working on an issue

If you found an issue that interests you, comment on that issue what your plans are. If the solution to the issue is clear, you can immediately create a pull request (see below). Otherwise, say what your proposed solution is and wait for a discussion around it.

Tip

Feel free to ping us after a few days if there are no responses.

If your solution involves code (or something that requires running the package locally), check the developer documentation. Otherwise, you can use the GitHub interface directly to create your pull request.

Additions and modifications to the template

If you have any new idea or think the template needs to be updated or fixed, please search our issues and if there isn't anything relevant, open a new issue.

+Contributing guidelines · BestieTemplate.jl

Contributing guidelines

First of all, thanks for the interest!

We welcome all kinds of contribution, including, but not limited to code, documentation, examples, configuration, issue creating, etc.

Be polite and respectful, and follow the code of conduct.

Bug reports and discussions

If you think you found a bug, feel free to open an issue. Focused suggestions and requests can also be opened as issues. Before opening a pull request, start an issue or a discussion on the topic, please.

Working on an issue

If you found an issue that interests you, comment on that issue what your plans are. If the solution to the issue is clear, you can immediately create a pull request (see below). Otherwise, say what your proposed solution is and wait for a discussion around it.

Tip

Feel free to ping us after a few days if there are no responses.

If your solution involves code (or something that requires running the package locally), check the developer documentation. Otherwise, you can use the GitHub interface directly to create your pull request.

Additions and modifications to the template

If you have any new idea or think the template needs to be updated or fixed, please search our issues and if there isn't anything relevant, open a new issue.

diff --git a/dev/91-developer/index.html b/dev/91-developer/index.html index bb2bc2f..043ba0b 100644 --- a/dev/91-developer/index.html +++ b/dev/91-developer/index.html @@ -25,4 +25,4 @@ - Alice {% if AddBob %}- Bob{% endif} - Carlos -- Diana

Dependent files and directories

To make a file depend on a variable, you can change the name of the file to include the conditional and the .jinja extension.

{% if AddSomeFile %}some-file.txt{% endif %}.jinja

If AddSomeFile, then some-file.txt will exist.

For directories, you do the same, except that you don't add the .jinja extension.

{% if AddGitHubTemplates %}ISSUE_TEMPLATE{% endif %}

Using answers

To use the answers of a question outside of a conditional, you can use {{ SomeValue }}. This will translate to the value of SomeValue as answered by the user. For instance

whoami() = "Hi, I'm package {{ PackageName }}.jl"

This also works on file names and in the copier.yml file.

Raw tag and avoiding clashes in GitHub workflow files

Since the GitHub workflow also uses { and } for their commands, we want to enclose them using the {% raw %}...{% endraw %} tag:

os: {% raw %}%{{ matrix.os }}{% endraw %}

Removing/replacing a question

Warn

This has only been tested with a single change

Before removing a question, we should deprecate it for one major release. We also want to ensure a smooth transition when the user updates.

Luckily, we do have one test that minimally simulates this situation: "Test updating from main to HEAD vs generate in HEAD" inside file test/test-bestie-specific-api.

This test will run generate using the local main branch (which won't contain the changes), and run the update command, with defaults=true, and then compare the result to running generate directly.

+- Diana

Dependent files and directories

To make a file depend on a variable, you can change the name of the file to include the conditional and the .jinja extension.

{% if AddSomeFile %}some-file.txt{% endif %}.jinja

If AddSomeFile, then some-file.txt will exist.

For directories, you do the same, except that you don't add the .jinja extension.

{% if AddGitHubTemplates %}ISSUE_TEMPLATE{% endif %}

Using answers

To use the answers of a question outside of a conditional, you can use {{ SomeValue }}. This will translate to the value of SomeValue as answered by the user. For instance

whoami() = "Hi, I'm package {{ PackageName }}.jl"

This also works on file names and in the copier.yml file.

Raw tag and avoiding clashes in GitHub workflow files

Since the GitHub workflow also uses { and } for their commands, we want to enclose them using the {% raw %}...{% endraw %} tag:

os: {% raw %}%{{ matrix.os }}{% endraw %}

Removing/replacing a question

Warn

This has only been tested with a single change

Before removing a question, we should deprecate it for one major release. We also want to ensure a smooth transition when the user updates.

Luckily, we do have one test that minimally simulates this situation: "Test updating from main to HEAD vs generate in HEAD" inside file test/test-bestie-specific-api.

This test will run generate using the local main branch (which won't contain the changes), and run the update command, with defaults=true, and then compare the result to running generate directly.

diff --git a/dev/95-reference/index.html b/dev/95-reference/index.html index b0ab996..424196f 100644 --- a/dev/95-reference/index.html +++ b/dev/95-reference/index.html @@ -1,6 +1,6 @@ -Reference · BestieTemplate.jl

Reference

Contents

Index

Auto docs

BestieTemplate.BestieTemplateModule

BestieTemplate.jl

This package defines a copier template for Julia packages and a basic user interface around copier to use it from Julia.

The main functions are: generate, apply, and update.

To create a new package using BestieTemplate run

julia> BestieTemplate.generate("path/to/YourNewPackage.jl")

To apply the template to an existing package

julia> BestieTemplate.apply("path/to/YourExistingPackage.jl")

Check the documentation: https://abelsiqueira.com/BestieTemplate.jl

source
BestieTemplate._copyMethod
_copy(src_path, dst_path, data; kwargs...)

Internal function to run common code for new or existing packages.

source
BestieTemplate._sanitize_package_nameMethod
package_name = _sanitize_package_name(path)

Sanitize the path to guess the package_name by looking at the base name and removing an extension. If the result is not a valid identifier, returns "".

source
BestieTemplate.applyFunction
apply(dst_path[, data]; kwargs...)
-apply(src_path, dst_path[, data]; true, kwargs...)

Applies the template to an existing project at path $dst_path$. If the dst_path does not exist, this will throw an error. For new packages, use BestieTemplate.generate instead.

Runs the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.

The data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.

Keyword arguments

  • guess:Bool = true: Whether to try to guess some of the data from the package itself.
  • warn_existing_pkg::Bool = true: Whether to check if you actually meant update. If you run apply and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.
  • quiet::Bool = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.

The other keyword arguments are passed directly to the internal Copier.copy.

source
BestieTemplate.generateFunction
generate(dst_path[, data]; kwargs...)
-generate(src_path, dst_path[, data]; true, kwargs...)

Generates a new project at the path dst_path using the template. If the dst_path already exists, this will throw an error, unless dst_path = ".". For existing packages, use BestieTemplate.apply instead.

Runs the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.

The data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.

Keyword arguments

  • warn_existing_pkg::Boolean = true: Whether to check if you actually meant update. If you run generate and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.
  • quiet::Boolean = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.

The other keyword arguments are passed directly to the internal Copier.copy.

source
BestieTemplate.updateFunction
update([data]; kwargs...)
-update(dst_path[, data]; kwargs...)

Run the update command of copier, updating the dst_path (or the current path if omitted) with a new version of the template with a new version of the template.

The data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.

Keyword arguments

The keyword arguments are passed directly to the internal Copier.update.

source
BestieTemplate.Copier.copyFunction
copy(dst_path[, data]; kwargs...)
-copy(src_path, dst_path[, data]; kwargs...)

Wrapper around copier.run_copy.

This is an internal function, if BestieTemplate's main API is not sufficient, open an issue. Note: this is not Base.copy, inside the Copier module we shadow that name.

source

Debug auto docs

BestieTemplate.DebugModule

Module Debug

Tools for debugging Bestie. Nothing here is public API.

Warning

This file is not tested and not covered in codecov. Except for the data, it is not supposed to be used in the tests.

Noteworthy: BestieTemplate.Debug.Data

source
BestieTemplate.Debug.dbg_applyFunction
dbg_apply([dst_path, data]; data_choice=:minimum)

Convenience function to help debug apply. It runs apply with the dst_path destination and the given data (nothing by default).

It also uses a data_choice to determine fake starting data. This is passed to dbg_data.

It uses the pkgdir location of Bestie and adds the flags

  • defaults = true: Sent to copier to use the default answers.
  • quiet = true: Low verbosity.
  • overwrite = true: Overwrite all files.
  • vcs_ref = HEAD: Use the development version of the template, including dirty repo changes.
source
BestieTemplate.Debug.dbg_dataFunction
dbg_data(data_choice, more_data)

Returns the fake debug data merged with more_data. The options for data_choice are:

  • :nothing, :none: No random data.
  • :required, :req: Only the required data is generated. You get asked which choice of optional data.
  • :minimum, :min: The required data plus the choice "minimum" for optional data.
  • :recommended, :rec: The required data plus the choice "recommended" for optional data.
  • :ask: The required data plus the choice "ask". The optional questions will be asked.
  • :ask_default: Same as :ask plus the default answers for the optional questions.
  • :ask_and_say_no: Same as :ask plus answers no/false to the optional questions.
  • :ask_and_say_yes: Same as :ask plus answers yes/true to the optional questions.
source
BestieTemplate.Debug.dbg_generateFunction
dbg_generate([dst_path, data]; data_choice=:minimum)

Convenience function to help debug generate. It runs generate with the dst_path destination (random by default) and the given data (nothing by default).

It also uses a data_choice to determine fake starting data. This is passed to dbg_data.

It uses the pkgdir location of Bestie and adds the flags

  • defaults = true: Sent to copier to use the default answers.
  • quiet = true: Low verbosity.
  • vcs_ref = HEAD: Use the development version of the template, including dirty repo changes.
source
BestieTemplate.Debug.DataModule

Fake data for testing

  • Debug.Data: NamedTuple of Dictionaries with default data
    • Debug.Data.required: Required data if you use defaults = true
    • Debug.Data.strategy_minimum: Required data for strategy minimum, no defaults.
    • Debug.Data.strategy_recommended: Required data for strategy recommended, no defaults.
    • Debug.Data.strategy_ask: Required data for strategy ask, no defaults.
source
+Reference · BestieTemplate.jl

Reference

Contents

Index

Auto docs

BestieTemplate.BestieTemplateModule

BestieTemplate.jl

This package defines a copier template for Julia packages and a basic user interface around copier to use it from Julia.

The main functions are: generate, apply, and update.

To create a new package using BestieTemplate run

julia> BestieTemplate.generate("path/to/YourNewPackage.jl")

To apply the template to an existing package

julia> BestieTemplate.apply("path/to/YourExistingPackage.jl")

Check the documentation: https://abelsiqueira.com/BestieTemplate.jl

source
BestieTemplate._copyMethod
_copy(src_path, dst_path, data; kwargs...)

Internal function to run common code for new or existing packages.

source
BestieTemplate._sanitize_package_nameMethod
package_name = _sanitize_package_name(path)

Sanitize the path to guess the package_name by looking at the base name and removing an extension. If the result is not a valid identifier, returns "".

source
BestieTemplate.applyFunction
apply(dst_path[, data]; kwargs...)
+apply(src_path, dst_path[, data]; true, kwargs...)

Applies the template to an existing project at path $dst_path$. If the dst_path does not exist, this will throw an error. For new packages, use BestieTemplate.generate instead.

Runs the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.

The data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.

Keyword arguments

  • guess:Bool = true: Whether to try to guess some of the data from the package itself.
  • warn_existing_pkg::Bool = true: Whether to check if you actually meant update. If you run apply and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.
  • quiet::Bool = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.

The other keyword arguments are passed directly to the internal Copier.copy.

source
BestieTemplate.generateFunction
generate(dst_path[, data]; kwargs...)
+generate(src_path, dst_path[, data]; true, kwargs...)

Generates a new project at the path dst_path using the template. If the dst_path already exists, this will throw an error, unless dst_path = ".". For existing packages, use BestieTemplate.apply instead.

Runs the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.

The data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.

Keyword arguments

  • warn_existing_pkg::Boolean = true: Whether to check if you actually meant update. If you run generate and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.
  • quiet::Boolean = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.

The other keyword arguments are passed directly to the internal Copier.copy.

source
BestieTemplate.updateFunction
update([data]; kwargs...)
+update(dst_path[, data]; kwargs...)

Run the update command of copier, updating the dst_path (or the current path if omitted) with a new version of the template with a new version of the template.

The data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.

Keyword arguments

The keyword arguments are passed directly to the internal Copier.update.

source
BestieTemplate.Copier.copyFunction
copy(dst_path[, data]; kwargs...)
+copy(src_path, dst_path[, data]; kwargs...)

Wrapper around copier.run_copy.

This is an internal function, if BestieTemplate's main API is not sufficient, open an issue. Note: this is not Base.copy, inside the Copier module we shadow that name.

source

Debug auto docs

BestieTemplate.DebugModule

Module Debug

Tools for debugging Bestie. Nothing here is public API.

Warning

This file is not tested and not covered in codecov. Except for the data, it is not supposed to be used in the tests.

Noteworthy: BestieTemplate.Debug.Data

source
BestieTemplate.Debug.dbg_applyFunction
dbg_apply([dst_path, data]; data_choice=:minimum)

Convenience function to help debug apply. It runs apply with the dst_path destination and the given data (nothing by default).

It also uses a data_choice to determine fake starting data. This is passed to dbg_data.

It uses the pkgdir location of Bestie and adds the flags

  • defaults = true: Sent to copier to use the default answers.
  • quiet = true: Low verbosity.
  • overwrite = true: Overwrite all files.
  • vcs_ref = HEAD: Use the development version of the template, including dirty repo changes.
source
BestieTemplate.Debug.dbg_dataFunction
dbg_data(data_choice, more_data)

Returns the fake debug data merged with more_data. The options for data_choice are:

  • :nothing, :none: No random data.
  • :required, :req: Only the required data is generated. You get asked which choice of optional data.
  • :minimum, :min: The required data plus the choice "minimum" for optional data.
  • :recommended, :rec: The required data plus the choice "recommended" for optional data.
  • :ask: The required data plus the choice "ask". The optional questions will be asked.
  • :ask_default: Same as :ask plus the default answers for the optional questions.
  • :ask_and_say_no: Same as :ask plus answers no/false to the optional questions.
  • :ask_and_say_yes: Same as :ask plus answers yes/true to the optional questions.
source
BestieTemplate.Debug.dbg_generateFunction
dbg_generate([dst_path, data]; data_choice=:minimum)

Convenience function to help debug generate. It runs generate with the dst_path destination (random by default) and the given data (nothing by default).

It also uses a data_choice to determine fake starting data. This is passed to dbg_data.

It uses the pkgdir location of Bestie and adds the flags

  • defaults = true: Sent to copier to use the default answers.
  • quiet = true: Low verbosity.
  • vcs_ref = HEAD: Use the development version of the template, including dirty repo changes.
source
BestieTemplate.Debug.DataModule

Fake data for testing

  • Debug.Data: NamedTuple of Dictionaries with default data
    • Debug.Data.required: Required data if you use defaults = true
    • Debug.Data.strategy_minimum: Required data for strategy minimum, no defaults.
    • Debug.Data.strategy_recommended: Required data for strategy recommended, no defaults.
    • Debug.Data.strategy_ask: Required data for strategy ask, no defaults.
source
diff --git a/dev/index.html b/dev/index.html index 9a49f1f..43809cc 100644 --- a/dev/index.html +++ b/dev/index.html @@ -37,4 +37,4 @@ - + diff --git a/dev/search_index.js b/dev/search_index.js index 03dd038..771d658 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"20-explanation/#explanation","page":"Explanation","title":"Explanation","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"In this section, we hope to explain the motivation for the package, and what is inside the template. Some things might have been obvious when creating the package and not at the moment, so feel free to create issues to ask, or suggest, clarifications.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"You can see all questions in details in the Questions page.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"tip: Tip\nIf something is missing or not explained enough, please open an issue.","category":"page"},{"location":"20-explanation/#The-engine,-the-project-generator,-and-the-template","page":"Explanation","title":"The engine, the project generator, and the template","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Let me start by marking some names clearer.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The template is the collection of files and folders written with some placeholders. For instance, the link to a GitHub project will be something like https://github.com/{{ PackageOwner }}/{{ PackageName }}.jl.\nThe engine is the tool that converts the template into the end result, by changing the placeholders into the actual values that we want.\nThe project generator is the tool that interacts with the user to get the placeholder values and give to the engine.","category":"page"},{"location":"20-explanation/#Comparison-with-existing-solutions","page":"Explanation","title":"Comparison with existing solutions","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Julia has a very good package generator called PkgTemplates.jl, so why did we create another one?","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The short answer is that we want a more streamlined development experience, a template more focused on best practices, and the ability to keep reusing the template whenever new tools and ideas are implemented.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"In more details, first, see the differences in the parts of the project in the table below:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":" BestieTemplate.jl PkgTemplates.jl\nTemplate Part of the package Part of the package\nEngine Jinja Mustache\nProject generator copier, with some wrappers in the package Part of the package","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Now, we can split this into three comparisons.","category":"page"},{"location":"20-explanation/#Template-differences","page":"Explanation","title":"Template differences","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The template differences are mostly due to opinion and contributions and it should be easy to translate files from one template to the other. We are heavily inspired by PkgTemplates.jl, as we used it for many years, but we made some changes in the hopes of improving software sustainability, package maintainability and code quality (which we just overtly simplify as best practices). As such, our current differences (as of the time of writing) are:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We have more best practices tools, such as pre-commit, configuration for linters and formatters for Julia, Markdown, TOML, YAML and JSON, CITATION.cff, Lint GitHub workflow, .editorconfig file, issues and pull requests templates, etc.\nWe focus on the main use cases (GitHub and GitHub actions), so we have much less options.","category":"page"},{"location":"20-explanation/#Engine-differences","page":"Explanation","title":"Engine differences","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We can't say much about these, since we don't know or care in details.","category":"page"},{"location":"20-explanation/#Project-generator-differences","page":"Explanation","title":"Project generator differences","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"PkgTemplates.jl is a project generator. This means that if you want to programmatically create templates inside Julia, this is the best solution. The questions (user interface) are implemented by the package, which then translates that into the answers for the engine. Disclaimer: We haven't worked on the package, this information is based on the docs.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We use copier as project generator. It is an external Python tool, so we also include some wrappers in the package to use it from Julia without the need to explicitly install it. Copier has many features, so we recommend that you check their comparisons pages for more information.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Most notably, the feature that made us choose copier in the first place has the ability to applied and reapplied to existing projects. This means that existing packages can benefit from all best practices that we provide. Furthermore, they can keep reaping benefits when we create new versions of the template.","category":"page"},{"location":"20-explanation/#Template-details","page":"Explanation","title":"Template details","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Let's dive into the details of the template now.","category":"page"},{"location":"20-explanation/#Recommended-vs-Minimum-vs-Others-(hidden)","page":"Explanation","title":"Recommended vs Minimum vs Others (hidden)","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The template contains a few required questions and then asks you whether you would like to use","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The \"recommended\" options, which include our current recommendation for best practices;\nThe \"minimum\" options, which answers \"no\" to everything, but still leaves you with a decent package to start; or\nThe option to answer every optional question individually.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The motivation behind \"minimum\" vs \"recommended\" is:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The \"minimum\" option includes all the Julia package basic plus a few things we think are of interest to all use cases of package development. Normal use cases for the \"minimum\" option are:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"You are testing the template;\nYou are developing solo and wants to \"move fast and break things\";\nYour package is in very early stage.\nYou are installing the \"minimum\" before installing the \"recommended\" to decrease the PR size.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Our loose criteria to make something part of the minimum is (exceptions may apply):","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"It is not too intrusive to development (e.g., .editorconfig);\nIt is a very common practice or tool (e.g., TagBot.yml and CompatHelper.yml);\nIt is a very strong recommendation that we think you should adopt (e.g., docs).","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The \"recommended\" option includes all the minimum things plus things that we believe will improve quality and sustainability of packages. Normal use cases for the \"recommended\" option are:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"You have a large package or a collection of packages;\nYou are not developing the package alone;\nYou expect open source contributions;\nYou agree with the best practices.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Our loose criteria to make something part of the recommended, but not minimum, is (exceptions may apply):","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Despite being good, it requires change of behaviour (e.g., pre-commit);\nIt does not make sense for solo devs (e.g., all-contributors);\nIt creates friction - which is good to ensure quality but slows developement (e.g., issue templates).","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Finally, there are other optional features. These are neither recommended nor part of the minimum template, which means that unless you (know and) set them explicitly, you are not using them.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The loose criteria to make something not recommended, nor minimum, is:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"It is a best practice, but for a niche audience (e.g., .cirrus.yml for testing on FreeBSD);","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"To see all the questions, head to Questions.","category":"page"},{"location":"20-explanation/#Basic-package-structure","page":"Explanation","title":"Basic package structure","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"This is the basic structure of a package:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"PackageName.jl/\nsrc/\nPackageName.jl\ntest/\nProject.toml\nruntests.jl\nLICENSE.md\nProject.toml\nREADME.md","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"With the exception of test/Project.toml, all other files are requirements to register a package.","category":"page"},{"location":"20-explanation/#Documentation","page":"Explanation","title":"Documentation","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"On top of the basic structure, we add some Documenter.jl structure.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"docs/\nsrc/\n90-contributing.md\n91-developer.md\n95-reference.md\nindex.md\nmake.jl\nProject.toml","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Brief explanation of the details:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The Project.toml, make.jl and src/index.md are the basic structure.\ndocs/src/90-contributing.md: Sometimes added as CONTRIBUTING.md, it explains how contributors can get involved in the project.\ndocs/src/91-developer.md: Sometimes added as README.dev.md or DEVELOPER.md, it explains how to setup your local environment and other information relevant for developers only.\ndocs/src/95-reference.md is the API reference page, which include an @autodocs.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"One noteworthy aspect of our make.jl, is that we include some code to automatically generate the list of pages. Create a file in the form ##-name.md, where ## is a two-digit number, and it will be automatically added to the pages list.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"info: index.md\nYou might have noticed that index.md is not numbered, and that is because Documenter.jl checks for that files specifically to define the landing page. Instead, we explicitly add \"Home\" => \"index.\" to make.jl.","category":"page"},{"location":"20-explanation/#Linting-and-Formatting","page":"Explanation","title":"Linting and Formatting","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The most important file related to linting and formatting is .pre-commit-config.yaml, which is the configuration for pre-commit. It defines a list of linters and formatters for Julia, Markdown, TOML, YAML, and JSON.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"It requires installing pre-commit (I recommend installing it globally with pipx). Installing pre-commit (pre-commit install) will make sure that it runs the relevant hooks before committing. Furthermore, if you run pre-commit run -a, it runs all hooks.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Some hooks in the .pre-commit-config.yaml file have configuration files of their own: .JuliaFormatter.toml, .markdownlint.json, .lychee.toml, and .yamllint.yml.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Also slightly related, is the .editorconfig file, which tells your editor, if you install the correct plugin, how to format some things.","category":"page"},{"location":"20-explanation/#GitHub-Workflows","page":"Explanation","title":"GitHub Workflows","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We have a few workflows, with plans to expand in the future:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"CompatHelper.yml: Should be well known by now. It checks that your Project.toml compat entries are up-to-date.\nCopier.yml: This will periodically check the template for updates. If there are updates, this action creates a pull request updating your repo.\nDocs.yml: Build the docs. Only runs when relevant files change.\nLint.yml: Run the linter and formatter through the command pre-commit run -a.\nTagBot.yml: Create GitHub releases automatically after your new release is merged on the Registry.\nFor testing, we have\nReusableTest.yml: Defines a reusable workflow with the testing.\nTest.yml: Defines a matrix of tests to be run whenever main is updated or a tag is created. Uses the ReusableTest workflow. If \"Simplified PR Test\" was not chosen, then this also runs when there are pull requests.\nTestOnPRs.yml: Defines a test to be run when pull requests are created. Only the latest stable Julia version is tested on a ubuntu-latest image. Uses the ReusableTest workflow. If \"Simplified PR Test\" was not chosen, then this file does not exist.","category":"page"},{"location":"20-explanation/#Issues-and-PR-templates","page":"Explanation","title":"Issues and PR templates","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We include issues and PR templates for GitHub (see .github/). These provide a starting point to your project management.","category":"page"},{"location":"20-explanation/#Other-files","page":"Explanation","title":"Other files","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":".cirrus.yml: For Cirrus CI, which we use solely for FreeBSD testing.\nCITATION.cff: Instead of the more classic .bib, we use .cff, which serves a better purpose of providing the metadata of the package. CFF files have been adopted by GitHub, so you can generate a BibTeX entry by clicking on \"Cite this repository\" on the repository's main page. CFF files have also been adopted by Zenodo to provide the metadata of your deposition.\nCODE_OF_CONDUCT.md: A code of conduct file from Contributor Covenant.","category":"page"},{"location":"91-developer/#dev_docs","page":"Developer documentation","title":"Developer documentation","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"note: Contributing guidelines\nIf you haven't, please read the Contributing guidelines first.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If you want to make contributions to this package that involves code, then this guide is for you.","category":"page"},{"location":"91-developer/#First-time-clone","page":"Developer documentation","title":"First time clone","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"tip: If you have writing rights\nIf you have writing rights, you don't have to fork. Instead, simply clone and skip ahead. Whenever upstream is mentioned, use origin instead.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If this is the first time you work with this repository, follow the instructions below to clone the repository.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Fork this repo\nClone your repo (this will create a git remote called origin)\nAdd this repo as a remote:\ngit remote add upstream https://github.com/abelsiqueira/BestieTemplate.jl","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This will ensure that you have two remotes in your git: origin and upstream. You will create branches and push to origin, and you will fetch and update your local main branch from upstream.","category":"page"},{"location":"91-developer/#Linting-and-formatting","page":"Developer documentation","title":"Linting and formatting","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Install a plugin on your editor to use EditorConfig. This will ensure that your editor is configured with important formatting settings.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"We use https://pre-commit.com to run the linters and formatters. In particular, the Julia code is formatted using JuliaFormatter.jl, so please install it globally first:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> # Press ]\npkg> activate\npkg> add JuliaFormatter","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To install pre-commit, we recommend using pipx as follows:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"# Install pipx following the link\npipx install pre-commit","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"With pre-commit installed, activate it as a pre-commit hook:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"pre-commit install","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To run the linting and formatting manually, enter the command below:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"pre-commit run -a","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Now, you can only commit if all the pre-commit tests pass.","category":"page"},{"location":"91-developer/#Testing","page":"Developer documentation","title":"Testing","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"As with most Julia packages, you can just open Julia in the repository folder, activate the environment, and run test:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> # press ]\npkg> activate .\npkg> test","category":"page"},{"location":"91-developer/#Testing-local-changes-to-the-template","page":"Developer documentation","title":"Testing local changes to the template","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"We have created tools to help test and debug changes to the template. These tools are subject to change without notice, but we will try to keep this section updated.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"My normal testing strategy is","category":"page"},{"location":"91-developer/#1.-Go-to-a-temp-path","page":"Developer documentation","title":"1. Go to a temp path","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"On Linux and OSX you should be able to use cd $(mktemp -d), but you can also use julia:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> cd(mktempdir()) # creates a temporary folder and enter it\njulia> pwd() # shows where you are","category":"page"},{"location":"91-developer/#2.-pkg-dev-the-Bestie-path","page":"Developer documentation","title":"2. pkg> dev the Bestie path","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Now, in a temporary folder, start Julia if you haven't and do the following:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> # press ]\npkg> dev full/path/to/bestie\npkg> # press backspace\njulia> using BestieTemplate","category":"page"},{"location":"91-developer/#3.-Use-the-debug-tools","page":"Developer documentation","title":"3. Use the debug tools","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> Dbg = BestieTemplate.Debug\njulia> Dbg.Data # module for the various data examples\njulia> Dbg.dbg_generate # to test generate\njulia> Dbg.dbg_apply # to test apply","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To check everything available in the Debug module, check the Debug auto docs.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"The minimum that you need is:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> Dbg.dbg_generate()","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This will create a new folder inside the current temporary folder with a name like PkgDebugBestieX. The X is a number automatically increased. It will use the path of the Bestie that you deved, and it will use some fake data, some defaults, and the \"minimum\" strategy.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If you want to change the data being used, you can give the keyword argument data_choice:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> Dbg.dbg_generate(data_choice = :rec)","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This will use the \"recommended\" strategy. Check BestieTemplate.Debug.dbg_data to see all options.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Check the full docs and the code for more details on what dbg_generate can do.","category":"page"},{"location":"91-developer/#Alternative:-use-copier-directly","page":"Developer documentation","title":"Alternative: use copier directly","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"You can also use copier directly to test the template. You just have to run copier with the --vcs-ref HEAD flag and point to your local clone:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"copier copy --vcs-ref HEAD /path/to/bestie/ pkg","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Of course, in this case you won't have the pre-filled data, so it isn't the preferred way for longer testing/debugging sessions.","category":"page"},{"location":"91-developer/#Working-on-a-new-issue","page":"Developer documentation","title":"Working on a new issue","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"We try to keep a linear history in this repo, so it is important to keep your branches up-to-date.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Fetch from the remote and fast-forward your local main\ngit fetch upstream\ngit switch main\ngit merge --ff-only upstream/main\nBranch from main to address the issue (see below for naming)\ngit switch -c 42-add-answer-universe\nPush the new local branch to your personal remote repository\ngit push -u origin 42-add-answer-universe\nCreate a pull request to merge your remote branch into the org main.","category":"page"},{"location":"91-developer/#Branch-naming","page":"Developer documentation","title":"Branch naming","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If there is an associated issue, add the issue number.\nIf there is no associated issue, and the changes are small, add a prefix such as \"typo\", \"hotfix\", \"small-refactor\", according to the type of update.\nIf the changes are not small and there is no associated issue, then create the issue first, so we can properly discuss the changes.\nUse dash separated imperative wording related to the issue (e.g., 14-add-tests, 15-fix-model, 16-remove-obsolete-files).","category":"page"},{"location":"91-developer/#Commit-message","page":"Developer documentation","title":"Commit message","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Use imperative or present tense, for instance: Add feature or Fix bug.\nHave informative titles.\nWhen necessary, add a body with details.\nIf there are breaking changes, add the information to the commit message.","category":"page"},{"location":"91-developer/#Before-creating-a-pull-request","page":"Developer documentation","title":"Before creating a pull request","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"tip: Atomic git commits\nTry to create \"atomic git commits\" (recommended reading: The Utopic Git History).","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Make sure the tests pass.\nMake sure the pre-commit tests pass.\nFetch any main updates from upstream and rebase your branch, if necessary:\ngit fetch upstream\ngit rebase upstream/main BRANCH_NAME\nThen you can open a pull request and work with the reviewer to address any issues.","category":"page"},{"location":"91-developer/#Building-and-viewing-the-documentation-locally","page":"Developer documentation","title":"Building and viewing the documentation locally","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Following the latest suggestions, we recommend using LiveServer to build the documentation. Here is how you do it:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Run julia --project=docs to open Julia in the environment of the docs.\nIf this is the first time building the docs\nPress ] to enter pkg mode\nRun pkg> dev . to use the development version of your package\nPress backspace to leave pkg mode\nRun julia> using LiveServer\nRun julia> servedocs()","category":"page"},{"location":"91-developer/#Making-a-new-release","page":"Developer documentation","title":"Making a new release","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To create a new release, you can follow these simple steps:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Create a branch release-x.y.z\nUpdate version in Project.toml\nUpdate the CHANGELOG.md:\nRename the section \"Unreleased\" to \"[x.y.z] - yyyy-mm-dd\" (i.e., version under brackets, dash, and date in ISO format)\nAdd a new section on top of it named \"Unreleased\"\nAdd a new link in the bottom for version \"x.y.z\"\nChange the \"[unreleased]\" link to use the latest version - end of line, vx.y.z ... HEAD.\nCreate a commit \"Release vx.y.z\", push, create a PR, wait for it to pass, merge the PR.\nGo back to main screen and click on the latest commit (link: https://github.com/abelsiqueira/BestieTemplate.jl/commit/main)\nAt the bottom, write @JuliaRegistrator register","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"After that, you only need to wait and verify:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Wait for the bot to comment (should take < 1m) with a link to a RP to the registry\nFollow the link and wait for a comment on the auto-merge\nThe comment should said all is well and auto-merge should occur shortly\nAfter the merge happens, TagBot will trigger and create a new GitHub tag. Check on https://github.com/abelsiqueira/BestieTemplate.jl/releases\nAfter the release is create, a \"docs\" GitHub action will start for the tag.\nAfter it passes, a deploy action will run.\nAfter that runs, the stable docs should be updated. Check them and look for the version number.","category":"page"},{"location":"91-developer/#Additions-to-the-templates","page":"Developer documentation","title":"Additions to the templates","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"info: Suggestions are not here\nThis section is aimed at the developer working on a new question, if you have any new idea or think the template needs to be updated or fixed, please search our issues and if there isn't anything relevant, open a new issue.","category":"page"},{"location":"91-developer/#Creating-a-new-question","page":"Developer documentation","title":"Creating a new question","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To create a new question, you have to open the file copier.yml in the root. Find an appropriate place to add the question. Comments help identify the optional sections in the file.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Follow the other questions style and syntax. The gist of it is that you need:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"A CamelCase name.\nwhen: \"{{ AnswerStrategy == 'ask' }}\" if the question is optional.\nA type.\nA help: Short description or title (Longer description and details).\nA default, if the question is optional.\nTo default to true if \"Recommended\" or false for \"Minimum\", use {{ AnswerStrategy != 'minimum' }}.\nA description, which is not actually part of copier, but we use to further describe the question to users in the documentation (it gets rendered in Questions).","category":"page"},{"location":"91-developer/#Dependent-sections-in-a-file","page":"Developer documentation","title":"Dependent sections in a file","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To create a section in a file that depends on a variable, first add .jinja to the end of the file name and use something like","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"{% if AddSomeStuff %}\n...\n{% endif %}","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"AddSomeStuff is assumed to be boolean here, but you can use other conditions, such as {% if PackageName == 'Pkg' %}.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Notice that the empty spaces are included as well, so in some situation you might need to make it less readable. For instance, the code below will correctly parse into a list of three elements if AddBob is false.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"# Good\n\n- Alice{% if AddBob %}\n- Bob{% endif}\n- Carlos\n- Diana","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"While the code below will parse into two lists of one and two elements, respectively:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"# Bad\n- Alice\n{% if AddBob %}- Bob{% endif}\n- Carlos\n- Diana","category":"page"},{"location":"91-developer/#Dependent-files-and-directories","page":"Developer documentation","title":"Dependent files and directories","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To make a file depend on a variable, you can change the name of the file to include the conditional and the .jinja extension.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"{% if AddSomeFile %}some-file.txt{% endif %}.jinja","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If AddSomeFile, then some-file.txt will exist.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"For directories, you do the same, except that you don't add the .jinja extension.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"{% if AddGitHubTemplates %}ISSUE_TEMPLATE{% endif %}","category":"page"},{"location":"91-developer/#Using-answers","page":"Developer documentation","title":"Using answers","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To use the answers of a question outside of a conditional, you can use {{ SomeValue }}. This will translate to the value of SomeValue as answered by the user. For instance","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"whoami() = \"Hi, I'm package {{ PackageName }}.jl\"","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This also works on file names and in the copier.yml file.","category":"page"},{"location":"91-developer/#Raw-tag-and-avoiding-clashes-in-GitHub-workflow-files","page":"Developer documentation","title":"Raw tag and avoiding clashes in GitHub workflow files","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Since the GitHub workflow also uses { and } for their commands, we want to enclose them using the {% raw %}...{% endraw %} tag:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"os: {% raw %}%{{ matrix.os }}{% endraw %}","category":"page"},{"location":"91-developer/#Removing/replacing-a-question","page":"Developer documentation","title":"Removing/replacing a question","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"warn: Warn\nThis has only been tested with a single change","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Before removing a question, we should deprecate it for one major release. We also want to ensure a smooth transition when the user updates.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Luckily, we do have one test that minimally simulates this situation: \"Test updating from main to HEAD vs generate in HEAD\" inside file test/test-bestie-specific-api.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This test will run generate using the local main branch (which won't contain the changes), and run the update command, with defaults=true, and then compare the result to running generate directly.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Change the help field to start with \"(Deprecated in VERSION)\" (VERSION should be the next major release)\nSet when: false in the question\nUpdate the CHANGELOG\nEntry in Deprecated section\nAdd or update a \"Breaking notice\" in the beginning to inform of the changes\nMove the default questions answers in src/debug/Data.jl to the deprecated dictionary.\nMake sure that nothing depends on the old question\nIf necessary, change some default values to use the deprecated questions, to ensure a smooth transition.\nRemove the question in the next release","category":"page"},{"location":"30-questions/#Questions","page":"Questions","title":"Questions","text":"","category":"section"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"In this page we list all the questions of the template, in the order that they are asked. Some of these questions are skipped because they are guessed.","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"To answer any of these question via the Julia interface, you can pass a dictionary to the generate or apply functions. For instance:","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"using BestieTemplate\ncd(mktempdir()) do # hide\ndata = Dict(\n \"PackageName\" => \"NotMyPkg\",\n \"PackageOwner\" => \"bestie\",\n \"Authors\" => \"Bestie\",\n)\nBestieTemplate.generate(\n pkgdir(BestieTemplate), # hide\n \"MyPkg\",\n data,\n defaults=true, # Choose default for other questions - will fail if there is none\n quiet=true,\n vcs_ref=\"HEAD\", # hide\n)\nprint(read(\"MyPkg/Project.toml\", String))\nend # hide","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"note: Help wanted\nWe have not managed to create a table of contents because we can't create the anchors in the headers. If you have an idea of what to do, help is appreciated.","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"using Markdown, YAML\n\nsections = String[]\nquestions = Dict{String,Any}()\n\ndir = joinpath(@__DIR__, \"..\", \"..\")\n\nout = \"\"\n\nfor line in readlines(joinpath(dir, \"copier.yml\"))\n if startswith(\"!include\")(line)\n file = split(line)[2]\n section_name = basename(file) |> x -> splitext(x)[1]\n if section_name == \"constants\"\n continue\n end\n push!(sections, section_name)\n yaml = YAML.load_file(joinpath(dir, file))\n questions[section_name] = yaml\n end\nend\n\ntitle_override = Dict(\n \"ci\" => \"Continuous Integration\",\n)\ntitles = Dict(\n section => get(title_override, section, section) |> x -> replace(x, \"-\" => \" \") |> titlecase\n for section in sections\n)\n\nfor section in sections\n global out\n title = titles[section]\n out *= \"## Section: $title\\n\\n\"\n for question in questions[section]\n name, answers = question\n out *= \"### $name\\n\\n\"\n\n help = answers[\"help\"]\n out *= \"**Question (in the CLI)**: $help\\n\\n\"\n\n description = get(answers, \"description\", \"\")\n if description != \"\"\n out *= \"**Description:**\\n\"\n out *= join(\"> \" .* split(description, \"\\n\"), \"\\n>\\n\")\n end\n\n out *= \"\\n\\n\"\n end\nend\n\nMarkdown.parse(out)","category":"page"},{"location":"95-reference/#reference","page":"Reference","title":"Reference","text":"","category":"section"},{"location":"95-reference/#Contents","page":"Reference","title":"Contents","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Pages = [\"95-reference.md\"]","category":"page"},{"location":"95-reference/#Index","page":"Reference","title":"Index","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Pages = [\"95-reference.md\"]","category":"page"},{"location":"95-reference/#Auto-docs","page":"Reference","title":"Auto docs","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Modules = [BestieTemplate, BestieTemplate.Copier]","category":"page"},{"location":"95-reference/#BestieTemplate.BestieTemplate","page":"Reference","title":"BestieTemplate.BestieTemplate","text":"BestieTemplate.jl\n\nThis package defines a copier template for Julia packages and a basic user interface around copier to use it from Julia.\n\nThe main functions are: generate, apply, and update.\n\nTo create a new package using BestieTemplate run\n\njulia> BestieTemplate.generate(\"path/to/YourNewPackage.jl\")\n\nTo apply the template to an existing package\n\njulia> BestieTemplate.apply(\"path/to/YourExistingPackage.jl\")\n\nCheck the documentation: https://abelsiqueira.com/BestieTemplate.jl\n\n\n\n\n\n","category":"module"},{"location":"95-reference/#BestieTemplate._copy-Tuple{Any, Any, Any}","page":"Reference","title":"BestieTemplate._copy","text":"_copy(src_path, dst_path, data; kwargs...)\n\nInternal function to run common code for new or existing packages.\n\n\n\n\n\n","category":"method"},{"location":"95-reference/#BestieTemplate._read_data_from_existing_path-Tuple{Any}","page":"Reference","title":"BestieTemplate._read_data_from_existing_path","text":"data = _read_data_from_existing_path(dst_path)\n\nReads the destination folder to figure out some answers.\n\n\n\n\n\n","category":"method"},{"location":"95-reference/#BestieTemplate._sanitize_package_name-Tuple{Any}","page":"Reference","title":"BestieTemplate._sanitize_package_name","text":"package_name = _sanitize_package_name(path)\n\nSanitize the path to guess the package_name by looking at the base name and removing an extension. If the result is not a valid identifier, returns \"\".\n\n\n\n\n\n","category":"method"},{"location":"95-reference/#BestieTemplate.apply","page":"Reference","title":"BestieTemplate.apply","text":"apply(dst_path[, data]; kwargs...)\napply(src_path, dst_path[, data]; true, kwargs...)\n\nApplies the template to an existing project at path dst_path. If the dst_path does not exist, this will throw an error. For new packages, use BestieTemplate.generate instead.\n\nRuns the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.\n\nThe data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.\n\nKeyword arguments\n\nguess:Bool = true: Whether to try to guess some of the data from the package itself.\nwarn_existing_pkg::Bool = true: Whether to check if you actually meant update. If you run apply and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.\nquiet::Bool = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.\n\nThe other keyword arguments are passed directly to the internal Copier.copy.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.generate","page":"Reference","title":"BestieTemplate.generate","text":"generate(dst_path[, data]; kwargs...)\ngenerate(src_path, dst_path[, data]; true, kwargs...)\n\nGenerates a new project at the path dst_path using the template. If the dst_path already exists, this will throw an error, unless dst_path = \".\". For existing packages, use BestieTemplate.apply instead.\n\nRuns the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.\n\nThe data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.\n\nKeyword arguments\n\nwarn_existing_pkg::Boolean = true: Whether to check if you actually meant update. If you run generate and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.\nquiet::Boolean = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.\n\nThe other keyword arguments are passed directly to the internal Copier.copy.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.update","page":"Reference","title":"BestieTemplate.update","text":"update([data]; kwargs...)\nupdate(dst_path[, data]; kwargs...)\n\nRun the update command of copier, updating the dst_path (or the current path if omitted) with a new version of the template with a new version of the template.\n\nThe data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.\n\nKeyword arguments\n\nThe keyword arguments are passed directly to the internal Copier.update.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Copier","page":"Reference","title":"BestieTemplate.Copier","text":"Wrapper around copier.\n\nThere are three functions in this module:\n\ncopy\nrecopy\nupdate\n\n\n\n\n\n","category":"module"},{"location":"95-reference/#BestieTemplate.Copier.copy","page":"Reference","title":"BestieTemplate.Copier.copy","text":"copy(dst_path[, data]; kwargs...)\ncopy(src_path, dst_path[, data]; kwargs...)\n\nWrapper around copier.run_copy.\n\nThis is an internal function, if BestieTemplate's main API is not sufficient, open an issue. Note: this is not Base.copy, inside the Copier module we shadow that name.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Copier.recopy","page":"Reference","title":"BestieTemplate.Copier.recopy","text":"recopy(dst_path[, data]; kwargs...)\n\nWrapper around copier.run_recopy.\n\nThis is an internal function, if BestieTemplate's main API is not sufficient, open an issue.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Copier.update","page":"Reference","title":"BestieTemplate.Copier.update","text":"update(dst_path[, data]; kwargs...)\n\nWrapper around copier.run_update.\n\nThis is an internal function, if BestieTemplate's main API is not sufficient, open an issue.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#Debug-auto-docs","page":"Reference","title":"Debug auto docs","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Modules = [BestieTemplate.Debug, BestieTemplate.Debug.Data]","category":"page"},{"location":"95-reference/#BestieTemplate.Debug","page":"Reference","title":"BestieTemplate.Debug","text":"Module Debug\n\nTools for debugging Bestie. Nothing here is public API.\n\nwarning: Warning\nThis file is not tested and not covered in codecov. Except for the data, it is not supposed to be used in the tests.\n\nNoteworthy: BestieTemplate.Debug.Data\n\n\n\n\n\n","category":"module"},{"location":"95-reference/#BestieTemplate.Debug.dbg_apply","page":"Reference","title":"BestieTemplate.Debug.dbg_apply","text":"dbg_apply([dst_path, data]; data_choice=:minimum)\n\nConvenience function to help debug apply. It runs apply with the dst_path destination and the given data (nothing by default).\n\nIt also uses a data_choice to determine fake starting data. This is passed to dbg_data.\n\nIt uses the pkgdir location of Bestie and adds the flags\n\ndefaults = true: Sent to copier to use the default answers.\nquiet = true: Low verbosity.\noverwrite = true: Overwrite all files.\nvcs_ref = HEAD: Use the development version of the template, including dirty repo changes.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Debug.dbg_data","page":"Reference","title":"BestieTemplate.Debug.dbg_data","text":"dbg_data(data_choice, more_data)\n\nReturns the fake debug data merged with more_data. The options for data_choice are:\n\n:nothing, :none: No random data.\n:required, :req: Only the required data is generated. You get asked which choice of optional data.\n:minimum, :min: The required data plus the choice \"minimum\" for optional data.\n:recommended, :rec: The required data plus the choice \"recommended\" for optional data.\n:ask: The required data plus the choice \"ask\". The optional questions will be asked.\n:ask_default: Same as :ask plus the default answers for the optional questions.\n:ask_and_say_no: Same as :ask plus answers no/false to the optional questions.\n:ask_and_say_yes: Same as :ask plus answers yes/true to the optional questions.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Debug.dbg_generate","page":"Reference","title":"BestieTemplate.Debug.dbg_generate","text":"dbg_generate([dst_path, data]; data_choice=:minimum)\n\nConvenience function to help debug generate. It runs generate with the dst_path destination (random by default) and the given data (nothing by default).\n\nIt also uses a data_choice to determine fake starting data. This is passed to dbg_data.\n\nIt uses the pkgdir location of Bestie and adds the flags\n\ndefaults = true: Sent to copier to use the default answers.\nquiet = true: Low verbosity.\nvcs_ref = HEAD: Use the development version of the template, including dirty repo changes.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Debug.Data","page":"Reference","title":"BestieTemplate.Debug.Data","text":"Fake data for testing\n\nDebug.Data: NamedTuple of Dictionaries with default data\nDebug.Data.required: Required data if you use defaults = true\nDebug.Data.strategy_minimum: Required data for strategy minimum, no defaults.\nDebug.Data.strategy_recommended: Required data for strategy recommended, no defaults.\nDebug.Data.strategy_ask: Required data for strategy ask, no defaults.\n\n\n\n\n\n","category":"module"},{"location":"90-contributing/#contributing","page":"Contributing guidelines","title":"Contributing guidelines","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"First of all, thanks for the interest!","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"We welcome all kinds of contribution, including, but not limited to code, documentation, examples, configuration, issue creating, etc.","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"Be polite and respectful, and follow the code of conduct.","category":"page"},{"location":"90-contributing/#Bug-reports-and-discussions","page":"Contributing guidelines","title":"Bug reports and discussions","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If you think you found a bug, feel free to open an issue. Focused suggestions and requests can also be opened as issues. Before opening a pull request, start an issue or a discussion on the topic, please.","category":"page"},{"location":"90-contributing/#Working-on-an-issue","page":"Contributing guidelines","title":"Working on an issue","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If you found an issue that interests you, comment on that issue what your plans are. If the solution to the issue is clear, you can immediately create a pull request (see below). Otherwise, say what your proposed solution is and wait for a discussion around it.","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"tip: Tip\nFeel free to ping us after a few days if there are no responses.","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If your solution involves code (or something that requires running the package locally), check the developer documentation. Otherwise, you can use the GitHub interface directly to create your pull request.","category":"page"},{"location":"90-contributing/#Additions-and-modifications-to-the-template","page":"Contributing guidelines","title":"Additions and modifications to the template","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If you have any new idea or think the template needs to be updated or fixed, please search our issues and if there isn't anything relevant, open a new issue.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"CurrentModule = BestieTemplate","category":"page"},{"location":"#BestieTemplate-Your-best-practices-friend","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"(Image: BestieTemplate.jl)","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"Welcome to the documentation of BestieTemplate.jl. This package provides a template in the copier engine for a Julia package. Furthermore, it provides a wrapper around convenience calls to that package.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"The main features of this package/template are:","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"It provides a curated (opinionated) list of tools and best practices for Julia package development;\nIt can be applied and reapplied to existing packages, allowing the updates in the template to be imported into the package;","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"(Image: asciicast)","category":"page"},{"location":"#Using","page":"BestieTemplate - Your best practices friend","title":"Using","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"To fully benefit from the template, there are some steps to be done before and after you generate your package. Check the full guide for more details.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"However, if you kinda know what you need to do, this is the TL;DR:","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"using> # press ]\npkg> add BestieTemplate\njulia> using BestieTemplate\njulia> BestieTemplate.generate(\"path/to/YourNewPackage.jl\")\njulia> # or BestieTemplate.apply(\"path/to/YourExistingPackage.jl\")","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"I really recommend checking the full guide, though.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"To understand more about our motivation and what the template provides, check the explanation page.","category":"page"},{"location":"#Getting-and-providing-help","page":"BestieTemplate - Your best practices friend","title":"Getting and providing help","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"I hope you find this package useful. If you have any questions, requests, or comments, check the issues and discussion pages.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"If you would like to get involved in the BestieTemplate growth, please check our contributing guide. We welcome contributions of many types, including coding, reviewing, creating issues, creating tutorials, interacting with users, etc. Make sure to follow our code of conduct.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"If your interest is in developing the package, check the development guide as well.","category":"page"},{"location":"#References","page":"BestieTemplate - Your best practices friend","title":"References","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"Here is a list of links/repos that include content that we have used for inspiration, or used directly. This is most likely not a complete list, since many of the things included here were based on existing packages and knowledge that we brought from other projects. This also doesn't explain where each file came from or why they are here. You can find some of that information in the Explanation section of the docs.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"PkgTemplates.jl, naturally. We used it for many years, and in particular for the initial TulipaEnergyModel.jl commit (see below).\nNetherlands eScience Center's python template includes many of the best practices that we apply here. We used many of the ideas there in a Julia context, and took many non-Julia specific ideas from there.\nTulipaEnergyModel.jl was the project that motivated this version of a template. From the start we decide to implement many best practices and so we started from a PkgTemplates.jl template and started adding parts of the python template that made sense.\nThe Julia Smooth Optimizers package ecosystem was one of the main motivations to look for a solution that could be applied and reapplied to existing packages, in particular to help maintainers.","category":"page"},{"location":"#Contributors","page":"BestieTemplate - Your best practices friend","title":"Contributors","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\"Abel
Abel Soares Siqueira

💻 📆 📖 🚧
\"Tangi
Tangi Migot

💻 📖 👀
\"Pablo
Pablo Rodríguez-Sánchez

📖 🤔
\"Olga
Olga Lyashevska

💻 📖 🤔
\"Luisa
Luisa Orozco

💻 📖 🤔
\"Netherlands
Netherlands eScience Center

💵
\"Suvayu
Suvayu Ali

🐛 👀 💻
\"Stefan
Stefan Verhoeven

💻 🤔
\"Dominique\"/
Dominique

🤔 💻
\"fdiblen\"/
fdiblen

💻 👀
\"Greg
Greg Neustroev

💻
\"Luca
Luca Ferranti

🤔
\"Guillaume
Guillaume Dalle

🤔
\"Johannes
Johannes Hidding

🐛 👀
\"Frames
Frames White

💻 🐛 🤔
\n\n\n\n\n\n","category":"page"},{"location":"10-full-guide/#full_guide","page":"Full guide","title":"Full guide","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Welcome to full usage guide of BestieTemplate.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Pages = [\"10-full-guide.md\"]\nDepth = 2:3","category":"page"},{"location":"10-full-guide/#Before-installing","page":"Full guide","title":"Before installing","text":"","category":"section"},{"location":"10-full-guide/#Things-to-know","page":"Full guide","title":"Things to know","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"This template is an attempt to provide many best practices to package development. This can be overwhelming, so you might prefer to take it easy at first and install only the fewest amount of new things possible.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Thinking of you, the first optional question in the template is how to deal with the optional questions:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The \"Recommended\" option lets us select the best practices that we like the most. This means \"yes\" to most of the optional answers.\nThe \"Minimum\" option does not add any optional feature. Your package will still be a valid Julia package with a few things that we deem essential (such as online testing, documentation, and CITATION.CFF).","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The \"Minimum\" option is still a step above the bare minimum for a Julia package, so you will still benefit from the template. The \"Recommended\" option adds many features that package maintainers might find useful in the long run, but might be too much at once. Check the Explanation page for more information.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you decide to gradually adopt, do this:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Follow the relevant application section for New or Existing.\nRemember to select the \"Minimum\" optional questions.\nFollow the Update section, change your answer from \"Minimum\" to \"Recommended\" or \"Ask me\".","category":"page"},{"location":"10-full-guide/#Things-to-install","page":"Full guide","title":"Things to install","text":"","category":"section"},{"location":"10-full-guide/#EditorConfig","page":"Full guide","title":"EditorConfig","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Install a plugin on your editor to use EditorConfig. This will ensure that your editor is configured with important formatting settings.","category":"page"},{"location":"10-full-guide/#pre-commit","page":"Full guide","title":"pre-commit","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"We recommend using https://pre-commit.com to run linters and formatters. If you select the \"recommended\" options later on, you will need pre-commit installed.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"pre-commit is a python package, so there are a few ways to install. We like one of these two ways:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Using pipx as follows:\npipx install pre-commit\nUsing pip in a virtual environment\npython -m venv env\nsource env/bin/activate\npip install pre-commit","category":"page"},{"location":"10-full-guide/#JuliaFormatter","page":"Full guide","title":"JuliaFormatter","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"When using pre-commit, the Julia code is formatted using JuliaFormatter.jl, so please install it globally first:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> # Press ]\npkg> activate\npkg> add JuliaFormatter","category":"page"},{"location":"10-full-guide/#Install-BestieTemplate-(or-copier)","page":"Full guide","title":"Install BestieTemplate (or copier)","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"To use the template, we recommend installing the package BestieTemplate.jl globally:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> # press ]\npkg> activate\npkg> add BestieTemplate","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The BestieTemplate package wraps copier and adds some lightweight checks and parameters to make your user experience better.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Alternative\nAlternatively, you can use copier directly, in which case you will have the pure template generation experience. If that is the case, I will assume that you know what you are doing and won't show the full command here to avoid confusing new users.","category":"page"},{"location":"10-full-guide/#Using-the-template","page":"Full guide","title":"Using the template","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"There are three use cases on using the template:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You are using the template to start a new package.\nYou already have a Julia project and you want to apply the template to your project.\nYou already uses the template and you want to update to get the latest changes.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The three cases are listed below.","category":"page"},{"location":"10-full-guide/#new_package","page":"Full guide","title":"New package","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Simply run","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> using BestieTemplate\njulia> BestieTemplate.generate(\"full/path/to/YourPackage.jl\")","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"This will create the folder at the given path and create a package named YourPackage using the latest release of the BestieTemplate. You will be prompted with many questions, some required and some with our recommended choices.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You can give more options to the generate function, including the source of the template, pre-filled data, and options passed to the underlying project generator copier. See the full docstring for BestieTemplate.generate for more information.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The resulting folder will not be a git package yet (to avoid trust issues), so you need to handle that yourself. You should see a short guide on screen, but here it is again:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"cd full/path/to/YourPackage.jl\ngit init\ngit add .\npre-commit run -a # Try to fix possible pre-commit issues (failures are expected)\ngit add .\ngit commit -m \"First commit\"\npre-commit install # Future commits can't be directly to main unless you use -n","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Now, create a new repository on GitHub and push your code. We won't give you details on how to do this, but you can check The Turing Way.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"After that, jump on to Setting up your package.","category":"page"},{"location":"10-full-guide/#existing_package","page":"Full guide","title":"Applying to an existing package","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"To apply the template to an existing package, you can do the following:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: git\nThis assumes that you already use git on that package and the your working directory is clean. It will fail otherwise.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> using BestieTemplate\njulia> BestieTemplate.apply(\"full/path/to/YourPackage.jl\")","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"This command will look around your project path and try to guess some of the answers. Currently, we guess:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"PackageName and PackageUUID from the name and uuid fields in Project.toml,\nAuthors from the authors field in Project.toml,\nPackageOwner from the repo in docs/make.jl,\nJuliaMinVersion from the compat section in Project.toml,\nIndentation from the indent field in .JuliaFormatter.toml.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"tip: Overwrite\nYou will be asked whether to overwrite existing files or not. Since you are using git, you can try it out and reset if you don't like the result.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you don't like the result, or want to override the answers, you can run the apply function with additional arguments, for instance:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> data = Dict(\"Authors\" => \"Bob \")\njulia> BestieTemplate.apply(\"full/path/to/YourPackage.jl\", data)","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Alternatively, you can also tell Bestie to not guess:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> BestieTemplate.apply(\"full/path/to/YourPackage.jl\"; guess = false)","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"See the full docstring for BestieTemplate.apply for more information.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You will most likely have conflicts when you apply the template. Whenever a conflict appears, you will need to decide on whether to accept or reject the new changes. Unfortunately, they are not shown to you when the conflict appears, so the best solution is to just accept all of them and then fix the conflicts using git.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Review the changes\nDon't just add the changes blindly, because some of your files can and will be overwritten.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: README.md conflicts\nWe really can't avoid some conflicts, and although some file can be skipped if existing (such as CITATION.cff), some can't. For instance, README.md will most likely be wrong when you apply the template, but the badges (for instance), need to be included in your project. This means that README.md cannot be skipped, and you will have to accept the overwrite and manually fix your README.md.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"tip: Formatting\nYou might most likely see changes in the formatting. So if you have are a formatter, it might be best to run it before reviewing the changes. If you have chosen the \"Recommended\" answers, or explicitly chose to add pre-commit, then you should use it now (see below).","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you need some help with undoing some of these changes, I recommend using a graphical interface. After the template is applied and you are happy with the conflict resolution, enable pre-commit and push your code.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"git add .\npre-commit run -a # Try to fix possible pre-commit issues (failures are expected)\npre-commit install # All commits will run pre-commit now\ngit add .\ngit commit -m \"Apply BestieTemplate vx.y.z\"","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Push your code to GitHub and head to Setting up your package for information on what to do next.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Now, go to Setting up your package to check what you still need to configure for your package.","category":"page"},{"location":"10-full-guide/#updating_package","page":"Full guide","title":"Updating","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"To update the package, simply call","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> BestieTemplate.update()","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You will be asked the relevant questions of the package as if you had applied it. The big differences are:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"It will only apply the things that are new since you last applied/updated\nIt will remember previous answer.\nIt will overwrite without asking.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"tip: Change previous answers\nYou can change your previous answers. In other words, if you though something was not mature enough in the past, but you are more confident in that now, you can adopt it now. This works even if the template was not updated itself.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"As with the first application, you need to run pre-commit run -a to fix the unavoidable linting and formatting issues. Check the modifications in the relevant linter and formatting files, if you changed them manually, before doing it, though.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"pre-commit run -a","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The underlying package copier will use git to apply the differences and it will overwrite whatever files it finds in the way. Since git is mandatory, the changes will be left for you to review.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Review the changes\nI repeat, the changes will be left for you to review. Don't just add them blindly, because some of your modifications can and will be overwritten.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you need some help with undoing some of these changes, I recommend using a graphical interface.","category":"page"},{"location":"10-full-guide/#Setting-up-your-package","page":"Full guide","title":"Setting up your package","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"There are various steps to setting up your package on GitHub. Some are important now, and some will be relevant when you try to make your first release.","category":"page"},{"location":"10-full-guide/#Add-to-GitHub","page":"Full guide","title":"Add to GitHub","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you haven't yet, create a repo on GitHub and push your code to it.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"info: Info\nThe actions will run and you will see errors in the documentation and linting. Do not despair.","category":"page"},{"location":"10-full-guide/#Documentation","page":"Full guide","title":"Documentation","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Go to your package setting on Github and find the \"Actions\" tab, the \"General\" link. On that page, find the \"Workflow permissions\" and change the selection to \"Read and write permissions\", and enable \"Allow GitHub Actions can create and approve pull requests\". This will allow the documentation workflow to work for development.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Go to the Actions page, click the failing Docs workflow and click on \"re-run all jobs\". It should pass now.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Now, go to your package setting on GitHub and find the \"Pages\" link. You should see an option to set the Source to \"Deploy from a branch\", and select the branch to be \"gh-pages\" and to deploy from the \"/ (root)\".","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"After circa 1 minute, you can check that the documentation was built properly.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"info: Info\nAt this point, you should have passing workflows.Tests should have been passing from the start.\nLint was fixed when we pushed the code to GitHub.\nDocs was fixed with the permissions change.","category":"page"},{"location":"10-full-guide/#Documentation-for-releases","page":"Full guide","title":"Documentation for releases","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"info: Info\nThis section is only relevant when making your first release, but it might be better to get it out of the way now.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You need to set a DOCUMENTER_KEY to build the documentation from the tags automatically when using TagBot (which we do by default). Do the following:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"pkg> activate --temp\npkg> add DocumenterTools\njulia> using DocumenterTools\njulia> DocumenterTools.genkeys(user=\"UserName\", repo=\"PackageName.jl\")","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Follow the instruction in the terminal.","category":"page"},{"location":"10-full-guide/#Enable-Codecov-for-code-coverage","page":"Full guide","title":"Enable Codecov for code coverage","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you don't have a Codecov account, go to https://codecov.io and create one now. After creating an account and logging in, you will see your main page with a list of your packages. Select the one that you are creating, it will open a configuration page.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"On the configuration page, select \"Using GitHub Actions\" as your CI. The first step in the list given you the CODECOV_TOKEN. Click on the \"repository secret\" link on that page. It should lead you to the GitHub settings > secrets and variables > actions, under a \"New secret\" screen. Write CODECOV_TOKEN on the \"Name\" field and paste the token that you see on codecov on the \"Secret\" field. Click \"Add secret\".","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Step 2 is not necessary because it is already present in the template.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The next time that the tests are run, the coverage page will be updated, and the badge will be fixed.","category":"page"},{"location":"10-full-guide/#Add-key-for-Copier.yml-workflow","page":"Full guide","title":"Add key for Copier.yml workflow","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Copier.yml is work in progress\nThis option is not selected by default because it is a work in progress. If you want to use it, you have to pass the key \"AddCopierCI\" => true to the data argument of generate or apply, or select \"Ask me\" when deciding how to answer the optional questions.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You can reapply the template in the future. This is normally a manual job, specially because normally there are conflicts. That being said, we are experimenting with having a workflow that automatically checks whether there are updates to the template and reapplies it. A Pull Request is created with the result.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Warning\nThis is optional, and in development, so you might want to delete the workflow instead.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you decide to use, here are the steps to set it up:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Create a Personal Access Token to be used by the Copier workflow.\nGo to https://github.com/settings/tokens.\nCreate a token with \"Content\", \"Pull-request\", and \"Workflows\" permissions.\nCopy the Token.\nGo to your YOUR_PACKAGE_URL/settings/secrets/actions.\nCreate a \"New repository secret\" named COPIER_PAT.","category":"page"},{"location":"10-full-guide/#CITATION.cff-and-Zenodo-deposition","page":"Full guide","title":"CITATION.cff and Zenodo deposition","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Update your CITATION.cff file with correct information. You can use cffinit to generate it easily.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Before releasing, enable Zenodo integration at https://zenodo.org/account/settings/github/ to automatically generate a deposition of your package, i.e., archive a version on Zenodo and generate a DOI.","category":"page"},{"location":"10-full-guide/#Update-README.md","page":"Full guide","title":"Update README.md","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Update the badges\nAdd a description","category":"page"},{"location":"10-full-guide/#Enable-discussions","page":"Full guide","title":"Enable discussions","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Enable GitHub discussions.","category":"page"},{"location":"10-full-guide/#First-release","page":"Full guide","title":"First release","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"When you are ready to make your first release, enable the Julia Registrator bot. Make sure that you haven't skipped these sections:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Documentation for releases\nCITATION.cff and Zenodo deposition","category":"page"}] +[{"location":"20-explanation/#explanation","page":"Explanation","title":"Explanation","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"In this section, we hope to explain the motivation for the package, and what is inside the template. Some things might have been obvious when creating the package and not at the moment, so feel free to create issues to ask, or suggest, clarifications.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"You can see all questions in details in the Questions page.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"tip: Tip\nIf something is missing or not explained enough, please open an issue.","category":"page"},{"location":"20-explanation/#The-engine,-the-project-generator,-and-the-template","page":"Explanation","title":"The engine, the project generator, and the template","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Let me start by marking some names clearer.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The template is the collection of files and folders written with some placeholders. For instance, the link to a GitHub project will be something like https://github.com/{{ PackageOwner }}/{{ PackageName }}.jl.\nThe engine is the tool that converts the template into the end result, by changing the placeholders into the actual values that we want.\nThe project generator is the tool that interacts with the user to get the placeholder values and give to the engine.","category":"page"},{"location":"20-explanation/#Comparison-with-existing-solutions","page":"Explanation","title":"Comparison with existing solutions","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Julia has a very good package generator called PkgTemplates.jl, so why did we create another one?","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The short answer is that we want a more streamlined development experience, a template more focused on best practices, and the ability to keep reusing the template whenever new tools and ideas are implemented.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"In more details, first, see the differences in the parts of the project in the table below:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":" BestieTemplate.jl PkgTemplates.jl\nTemplate Part of the package Part of the package\nEngine Jinja Mustache\nProject generator copier, with some wrappers in the package Part of the package","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Now, we can split this into three comparisons.","category":"page"},{"location":"20-explanation/#Template-differences","page":"Explanation","title":"Template differences","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The template differences are mostly due to opinion and contributions and it should be easy to translate files from one template to the other. We are heavily inspired by PkgTemplates.jl, as we used it for many years, but we made some changes in the hopes of improving software sustainability, package maintainability and code quality (which we just overtly simplify as best practices). As such, our current differences (as of the time of writing) are:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We have more best practices tools, such as pre-commit, configuration for linters and formatters for Julia, Markdown, TOML, YAML and JSON, CITATION.cff, Lint GitHub workflow, .editorconfig file, issues and pull requests templates, etc.\nWe focus on the main use cases (GitHub and GitHub actions), so we have much less options.","category":"page"},{"location":"20-explanation/#Engine-differences","page":"Explanation","title":"Engine differences","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We can't say much about these, since we don't know or care in details.","category":"page"},{"location":"20-explanation/#Project-generator-differences","page":"Explanation","title":"Project generator differences","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"PkgTemplates.jl is a project generator. This means that if you want to programmatically create templates inside Julia, this is the best solution. The questions (user interface) are implemented by the package, which then translates that into the answers for the engine. Disclaimer: We haven't worked on the package, this information is based on the docs.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We use copier as project generator. It is an external Python tool, so we also include some wrappers in the package to use it from Julia without the need to explicitly install it. Copier has many features, so we recommend that you check their comparisons pages for more information.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Most notably, the feature that made us choose copier in the first place has the ability to applied and reapplied to existing projects. This means that existing packages can benefit from all best practices that we provide. Furthermore, they can keep reaping benefits when we create new versions of the template.","category":"page"},{"location":"20-explanation/#Template-details","page":"Explanation","title":"Template details","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Let's dive into the details of the template now.","category":"page"},{"location":"20-explanation/#Recommended-vs-Minimum-vs-Others-(hidden)","page":"Explanation","title":"Recommended vs Minimum vs Others (hidden)","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The template contains a few required questions and then asks you whether you would like to use","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The \"recommended\" options, which include our current recommendation for best practices;\nThe \"minimum\" options, which answers \"no\" to everything, but still leaves you with a decent package to start; or\nThe option to answer every optional question individually.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The motivation behind \"minimum\" vs \"recommended\" is:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The \"minimum\" option includes all the Julia package basic plus a few things we think are of interest to all use cases of package development. Normal use cases for the \"minimum\" option are:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"You are testing the template;\nYou are developing solo and wants to \"move fast and break things\";\nYour package is in very early stage.\nYou are installing the \"minimum\" before installing the \"recommended\" to decrease the PR size.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Our loose criteria to make something part of the minimum is (exceptions may apply):","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"It is not too intrusive to development (e.g., .editorconfig);\nIt is a very common practice or tool (e.g., TagBot.yml and CompatHelper.yml);\nIt is a very strong recommendation that we think you should adopt (e.g., docs).","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The \"recommended\" option includes all the minimum things plus things that we believe will improve quality and sustainability of packages. Normal use cases for the \"recommended\" option are:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"You have a large package or a collection of packages;\nYou are not developing the package alone;\nYou expect open source contributions;\nYou agree with the best practices.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Our loose criteria to make something part of the recommended, but not minimum, is (exceptions may apply):","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Despite being good, it requires change of behaviour (e.g., pre-commit);\nIt does not make sense for solo devs (e.g., all-contributors);\nIt creates friction - which is good to ensure quality but slows developement (e.g., issue templates).","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Finally, there are other optional features. These are neither recommended nor part of the minimum template, which means that unless you (know and) set them explicitly, you are not using them.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The loose criteria to make something not recommended, nor minimum, is:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"It is a best practice, but for a niche audience (e.g., .cirrus.yml for testing on FreeBSD);","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"To see all the questions, head to Questions.","category":"page"},{"location":"20-explanation/#Basic-package-structure","page":"Explanation","title":"Basic package structure","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"This is the basic structure of a package:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"PackageName.jl/\nsrc/\nPackageName.jl\ntest/\nProject.toml\nruntests.jl\nLICENSE.md\nProject.toml\nREADME.md","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"With the exception of test/Project.toml, all other files are requirements to register a package.","category":"page"},{"location":"20-explanation/#Documentation","page":"Explanation","title":"Documentation","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"On top of the basic structure, we add some Documenter.jl structure.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"docs/\nsrc/\n90-contributing.md\n91-developer.md\n95-reference.md\nindex.md\nmake.jl\nProject.toml","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Brief explanation of the details:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The Project.toml, make.jl and src/index.md are the basic structure.\ndocs/src/90-contributing.md: Sometimes added as CONTRIBUTING.md, it explains how contributors can get involved in the project.\ndocs/src/91-developer.md: Sometimes added as README.dev.md or DEVELOPER.md, it explains how to setup your local environment and other information relevant for developers only.\ndocs/src/95-reference.md is the API reference page, which include an @autodocs.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"One noteworthy aspect of our make.jl, is that we include some code to automatically generate the list of pages. Create a file in the form ##-name.md, where ## is a two-digit number, and it will be automatically added to the pages list.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"info: index.md\nYou might have noticed that index.md is not numbered, and that is because Documenter.jl checks for that files specifically to define the landing page. Instead, we explicitly add \"Home\" => \"index.\" to make.jl.","category":"page"},{"location":"20-explanation/#Linting-and-Formatting","page":"Explanation","title":"Linting and Formatting","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"The most important file related to linting and formatting is .pre-commit-config.yaml, which is the configuration for pre-commit. It defines a list of linters and formatters for Julia, Markdown, TOML, YAML, and JSON.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"It requires installing pre-commit (I recommend installing it globally with pipx). Installing pre-commit (pre-commit install) will make sure that it runs the relevant hooks before committing. Furthermore, if you run pre-commit run -a, it runs all hooks.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Some hooks in the .pre-commit-config.yaml file have configuration files of their own: .JuliaFormatter.toml, .markdownlint.json, .lychee.toml, and .yamllint.yml.","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"Also slightly related, is the .editorconfig file, which tells your editor, if you install the correct plugin, how to format some things.","category":"page"},{"location":"20-explanation/#GitHub-Workflows","page":"Explanation","title":"GitHub Workflows","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We have a few workflows, with plans to expand in the future:","category":"page"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"CompatHelper.yml: Should be well known by now. It checks that your Project.toml compat entries are up-to-date.\nCopier.yml: This will periodically check the template for updates. If there are updates, this action creates a pull request updating your repo.\nDocs.yml: Build the docs. Only runs when relevant files change.\nLint.yml: Run the linter and formatter through the command pre-commit run -a.\nTagBot.yml: Create GitHub releases automatically after your new release is merged on the Registry.\nFor testing, we have\nReusableTest.yml: Defines a reusable workflow with the testing.\nTest.yml: Defines a matrix of tests to be run whenever main is updated or a tag is created. Uses the ReusableTest workflow. If \"Simplified PR Test\" was not chosen, then this also runs when there are pull requests.\nTestOnPRs.yml: Defines a test to be run when pull requests are created. Only the latest stable Julia version is tested on a ubuntu-latest image. Uses the ReusableTest workflow. If \"Simplified PR Test\" was not chosen, then this file does not exist.","category":"page"},{"location":"20-explanation/#Issues-and-PR-templates","page":"Explanation","title":"Issues and PR templates","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":"We include issues and PR templates for GitHub (see .github/). These provide a starting point to your project management.","category":"page"},{"location":"20-explanation/#Other-files","page":"Explanation","title":"Other files","text":"","category":"section"},{"location":"20-explanation/","page":"Explanation","title":"Explanation","text":".cirrus.yml: For Cirrus CI, which we use solely for FreeBSD testing.\nCITATION.cff: Instead of the more classic .bib, we use .cff, which serves a better purpose of providing the metadata of the package. CFF files have been adopted by GitHub, so you can generate a BibTeX entry by clicking on \"Cite this repository\" on the repository's main page. CFF files have also been adopted by Zenodo to provide the metadata of your deposition.\nCODE_OF_CONDUCT.md: A code of conduct file from Contributor Covenant.","category":"page"},{"location":"91-developer/#dev_docs","page":"Developer documentation","title":"Developer documentation","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"note: Contributing guidelines\nIf you haven't, please read the Contributing guidelines first.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If you want to make contributions to this package that involves code, then this guide is for you.","category":"page"},{"location":"91-developer/#First-time-clone","page":"Developer documentation","title":"First time clone","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"tip: If you have writing rights\nIf you have writing rights, you don't have to fork. Instead, simply clone and skip ahead. Whenever upstream is mentioned, use origin instead.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If this is the first time you work with this repository, follow the instructions below to clone the repository.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Fork this repo\nClone your repo (this will create a git remote called origin)\nAdd this repo as a remote:\ngit remote add upstream https://github.com/abelsiqueira/BestieTemplate.jl","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This will ensure that you have two remotes in your git: origin and upstream. You will create branches and push to origin, and you will fetch and update your local main branch from upstream.","category":"page"},{"location":"91-developer/#Linting-and-formatting","page":"Developer documentation","title":"Linting and formatting","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Install a plugin on your editor to use EditorConfig. This will ensure that your editor is configured with important formatting settings.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"We use https://pre-commit.com to run the linters and formatters. In particular, the Julia code is formatted using JuliaFormatter.jl, so please install it globally first:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> # Press ]\npkg> activate\npkg> add JuliaFormatter","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To install pre-commit, we recommend using pipx as follows:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"# Install pipx following the link\npipx install pre-commit","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"With pre-commit installed, activate it as a pre-commit hook:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"pre-commit install","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To run the linting and formatting manually, enter the command below:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"pre-commit run -a","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Now, you can only commit if all the pre-commit tests pass.","category":"page"},{"location":"91-developer/#Testing","page":"Developer documentation","title":"Testing","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"As with most Julia packages, you can just open Julia in the repository folder, activate the environment, and run test:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> # press ]\npkg> activate .\npkg> test","category":"page"},{"location":"91-developer/#Testing-local-changes-to-the-template","page":"Developer documentation","title":"Testing local changes to the template","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"We have created tools to help test and debug changes to the template. These tools are subject to change without notice, but we will try to keep this section updated.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"My normal testing strategy is","category":"page"},{"location":"91-developer/#1.-Go-to-a-temp-path","page":"Developer documentation","title":"1. Go to a temp path","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"On Linux and OSX you should be able to use cd $(mktemp -d), but you can also use julia:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> cd(mktempdir()) # creates a temporary folder and enter it\njulia> pwd() # shows where you are","category":"page"},{"location":"91-developer/#2.-pkg-dev-the-Bestie-path","page":"Developer documentation","title":"2. pkg> dev the Bestie path","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Now, in a temporary folder, start Julia if you haven't and do the following:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> # press ]\npkg> dev full/path/to/bestie\npkg> # press backspace\njulia> using BestieTemplate","category":"page"},{"location":"91-developer/#3.-Use-the-debug-tools","page":"Developer documentation","title":"3. Use the debug tools","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> Dbg = BestieTemplate.Debug\njulia> Dbg.Data # module for the various data examples\njulia> Dbg.dbg_generate # to test generate\njulia> Dbg.dbg_apply # to test apply","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To check everything available in the Debug module, check the Debug auto docs.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"The minimum that you need is:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> Dbg.dbg_generate()","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This will create a new folder inside the current temporary folder with a name like PkgDebugBestieX. The X is a number automatically increased. It will use the path of the Bestie that you deved, and it will use some fake data, some defaults, and the \"minimum\" strategy.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If you want to change the data being used, you can give the keyword argument data_choice:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"julia> Dbg.dbg_generate(data_choice = :rec)","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This will use the \"recommended\" strategy. Check BestieTemplate.Debug.dbg_data to see all options.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Check the full docs and the code for more details on what dbg_generate can do.","category":"page"},{"location":"91-developer/#Alternative:-use-copier-directly","page":"Developer documentation","title":"Alternative: use copier directly","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"You can also use copier directly to test the template. You just have to run copier with the --vcs-ref HEAD flag and point to your local clone:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"copier copy --vcs-ref HEAD /path/to/bestie/ pkg","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Of course, in this case you won't have the pre-filled data, so it isn't the preferred way for longer testing/debugging sessions.","category":"page"},{"location":"91-developer/#Working-on-a-new-issue","page":"Developer documentation","title":"Working on a new issue","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"We try to keep a linear history in this repo, so it is important to keep your branches up-to-date.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Fetch from the remote and fast-forward your local main\ngit fetch upstream\ngit switch main\ngit merge --ff-only upstream/main\nBranch from main to address the issue (see below for naming)\ngit switch -c 42-add-answer-universe\nPush the new local branch to your personal remote repository\ngit push -u origin 42-add-answer-universe\nCreate a pull request to merge your remote branch into the org main.","category":"page"},{"location":"91-developer/#Branch-naming","page":"Developer documentation","title":"Branch naming","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If there is an associated issue, add the issue number.\nIf there is no associated issue, and the changes are small, add a prefix such as \"typo\", \"hotfix\", \"small-refactor\", according to the type of update.\nIf the changes are not small and there is no associated issue, then create the issue first, so we can properly discuss the changes.\nUse dash separated imperative wording related to the issue (e.g., 14-add-tests, 15-fix-model, 16-remove-obsolete-files).","category":"page"},{"location":"91-developer/#Commit-message","page":"Developer documentation","title":"Commit message","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Use imperative or present tense, for instance: Add feature or Fix bug.\nHave informative titles.\nWhen necessary, add a body with details.\nIf there are breaking changes, add the information to the commit message.","category":"page"},{"location":"91-developer/#Before-creating-a-pull-request","page":"Developer documentation","title":"Before creating a pull request","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"tip: Atomic git commits\nTry to create \"atomic git commits\" (recommended reading: The Utopic Git History).","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Make sure the tests pass.\nMake sure the pre-commit tests pass.\nFetch any main updates from upstream and rebase your branch, if necessary:\ngit fetch upstream\ngit rebase upstream/main BRANCH_NAME\nThen you can open a pull request and work with the reviewer to address any issues.","category":"page"},{"location":"91-developer/#Building-and-viewing-the-documentation-locally","page":"Developer documentation","title":"Building and viewing the documentation locally","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Following the latest suggestions, we recommend using LiveServer to build the documentation. Here is how you do it:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Run julia --project=docs to open Julia in the environment of the docs.\nIf this is the first time building the docs\nPress ] to enter pkg mode\nRun pkg> dev . to use the development version of your package\nPress backspace to leave pkg mode\nRun julia> using LiveServer\nRun julia> servedocs()","category":"page"},{"location":"91-developer/#Making-a-new-release","page":"Developer documentation","title":"Making a new release","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To create a new release, you can follow these simple steps:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Create a branch release-x.y.z\nUpdate version in Project.toml\nUpdate the CHANGELOG.md:\nRename the section \"Unreleased\" to \"[x.y.z] - yyyy-mm-dd\" (i.e., version under brackets, dash, and date in ISO format)\nAdd a new section on top of it named \"Unreleased\"\nAdd a new link in the bottom for version \"x.y.z\"\nChange the \"[unreleased]\" link to use the latest version - end of line, vx.y.z ... HEAD.\nCreate a commit \"Release vx.y.z\", push, create a PR, wait for it to pass, merge the PR.\nGo back to main screen and click on the latest commit (link: https://github.com/abelsiqueira/BestieTemplate.jl/commit/main)\nAt the bottom, write @JuliaRegistrator register","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"After that, you only need to wait and verify:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Wait for the bot to comment (should take < 1m) with a link to a RP to the registry\nFollow the link and wait for a comment on the auto-merge\nThe comment should said all is well and auto-merge should occur shortly\nAfter the merge happens, TagBot will trigger and create a new GitHub tag. Check on https://github.com/abelsiqueira/BestieTemplate.jl/releases\nAfter the release is create, a \"docs\" GitHub action will start for the tag.\nAfter it passes, a deploy action will run.\nAfter that runs, the stable docs should be updated. Check them and look for the version number.","category":"page"},{"location":"91-developer/#Additions-to-the-templates","page":"Developer documentation","title":"Additions to the templates","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"info: Suggestions are not here\nThis section is aimed at the developer working on a new question, if you have any new idea or think the template needs to be updated or fixed, please search our issues and if there isn't anything relevant, open a new issue.","category":"page"},{"location":"91-developer/#Creating-a-new-question","page":"Developer documentation","title":"Creating a new question","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To create a new question, you have to open the file copier.yml in the root. Find an appropriate place to add the question. Comments help identify the optional sections in the file.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Follow the other questions style and syntax. The gist of it is that you need:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"A CamelCase name.\nwhen: \"{{ AnswerStrategy == 'ask' }}\" if the question is optional.\nA type.\nA help: Short description or title (Longer description and details).\nA default, if the question is optional.\nTo default to true if \"Recommended\" or false for \"Minimum\", use {{ AnswerStrategy != 'minimum' }}.\nA description, which is not actually part of copier, but we use to further describe the question to users in the documentation (it gets rendered in Questions).","category":"page"},{"location":"91-developer/#Dependent-sections-in-a-file","page":"Developer documentation","title":"Dependent sections in a file","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To create a section in a file that depends on a variable, first add .jinja to the end of the file name and use something like","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"{% if AddSomeStuff %}\n...\n{% endif %}","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"AddSomeStuff is assumed to be boolean here, but you can use other conditions, such as {% if PackageName == 'Pkg' %}.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Notice that the empty spaces are included as well, so in some situation you might need to make it less readable. For instance, the code below will correctly parse into a list of three elements if AddBob is false.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"# Good\n\n- Alice{% if AddBob %}\n- Bob{% endif}\n- Carlos\n- Diana","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"While the code below will parse into two lists of one and two elements, respectively:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"# Bad\n- Alice\n{% if AddBob %}- Bob{% endif}\n- Carlos\n- Diana","category":"page"},{"location":"91-developer/#Dependent-files-and-directories","page":"Developer documentation","title":"Dependent files and directories","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To make a file depend on a variable, you can change the name of the file to include the conditional and the .jinja extension.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"{% if AddSomeFile %}some-file.txt{% endif %}.jinja","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"If AddSomeFile, then some-file.txt will exist.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"For directories, you do the same, except that you don't add the .jinja extension.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"{% if AddGitHubTemplates %}ISSUE_TEMPLATE{% endif %}","category":"page"},{"location":"91-developer/#Using-answers","page":"Developer documentation","title":"Using answers","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"To use the answers of a question outside of a conditional, you can use {{ SomeValue }}. This will translate to the value of SomeValue as answered by the user. For instance","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"whoami() = \"Hi, I'm package {{ PackageName }}.jl\"","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This also works on file names and in the copier.yml file.","category":"page"},{"location":"91-developer/#Raw-tag-and-avoiding-clashes-in-GitHub-workflow-files","page":"Developer documentation","title":"Raw tag and avoiding clashes in GitHub workflow files","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Since the GitHub workflow also uses { and } for their commands, we want to enclose them using the {% raw %}...{% endraw %} tag:","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"os: {% raw %}%{{ matrix.os }}{% endraw %}","category":"page"},{"location":"91-developer/#Removing/replacing-a-question","page":"Developer documentation","title":"Removing/replacing a question","text":"","category":"section"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"warn: Warn\nThis has only been tested with a single change","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Before removing a question, we should deprecate it for one major release. We also want to ensure a smooth transition when the user updates.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Luckily, we do have one test that minimally simulates this situation: \"Test updating from main to HEAD vs generate in HEAD\" inside file test/test-bestie-specific-api.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"This test will run generate using the local main branch (which won't contain the changes), and run the update command, with defaults=true, and then compare the result to running generate directly.","category":"page"},{"location":"91-developer/","page":"Developer documentation","title":"Developer documentation","text":"Change the help field to start with \"(Deprecated in VERSION)\" (VERSION should be the next major release)\nSet when: false in the question\nUpdate the CHANGELOG\nEntry in Deprecated section\nAdd or update a \"Breaking notice\" in the beginning to inform of the changes\nMove the default questions answers in src/debug/Data.jl to the deprecated dictionary.\nMake sure that nothing depends on the old question\nIf necessary, change some default values to use the deprecated questions, to ensure a smooth transition.\nRemove the question in the next release","category":"page"},{"location":"30-questions/#Questions","page":"Questions","title":"Questions","text":"","category":"section"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"In this page we list all the questions of the template, in the order that they are asked. Some of these questions are skipped because they are guessed.","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"To answer any of these question via the Julia interface, you can pass a dictionary to the generate or apply functions. For instance:","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"using BestieTemplate\ncd(mktempdir()) do # hide\ndata = Dict(\n \"PackageName\" => \"NotMyPkg\",\n \"PackageOwner\" => \"bestie\",\n \"Authors\" => \"Bestie\",\n)\nBestieTemplate.generate(\n pkgdir(BestieTemplate), # hide\n \"MyPkg\",\n data,\n defaults=true, # Choose default for other questions - will fail if there is none\n quiet=true,\n vcs_ref=\"HEAD\", # hide\n)\nprint(read(\"MyPkg/Project.toml\", String))\nend # hide","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"note: Help wanted\nWe have not managed to create a table of contents because we can't create the anchors in the headers. If you have an idea of what to do, help is appreciated.","category":"page"},{"location":"30-questions/","page":"Questions","title":"Questions","text":"using Markdown, YAML\n\nsections = String[]\nquestions = Dict{String,Any}()\n\ndir = joinpath(@__DIR__, \"..\", \"..\")\n\nout = \"\"\n\nfor line in readlines(joinpath(dir, \"copier.yml\"))\n if startswith(\"!include\")(line)\n file = split(line)[2]\n section_name = basename(file) |> x -> splitext(x)[1]\n if section_name == \"constants\"\n continue\n end\n push!(sections, section_name)\n yaml = YAML.load_file(joinpath(dir, file))\n questions[section_name] = yaml\n end\nend\n\ntitle_override = Dict(\n \"ci\" => \"Continuous Integration\",\n)\ntitles = Dict(\n section => get(title_override, section, section) |> x -> replace(x, \"-\" => \" \") |> titlecase\n for section in sections\n)\n\nfor section in sections\n global out\n title = titles[section]\n out *= \"## Section: $title\\n\\n\"\n for question in questions[section]\n name, answers = question\n out *= \"### $name\\n\\n\"\n\n help = answers[\"help\"]\n out *= \"**Question (in the CLI)**: $help\\n\\n\"\n\n description = get(answers, \"description\", \"\")\n if description != \"\"\n out *= \"**Description:**\\n\"\n out *= join(\"> \" .* split(description, \"\\n\"), \"\\n>\\n\")\n end\n\n out *= \"\\n\\n\"\n end\nend\n\nMarkdown.parse(out)","category":"page"},{"location":"95-reference/#reference","page":"Reference","title":"Reference","text":"","category":"section"},{"location":"95-reference/#Contents","page":"Reference","title":"Contents","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Pages = [\"95-reference.md\"]","category":"page"},{"location":"95-reference/#Index","page":"Reference","title":"Index","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Pages = [\"95-reference.md\"]","category":"page"},{"location":"95-reference/#Auto-docs","page":"Reference","title":"Auto docs","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Modules = [BestieTemplate, BestieTemplate.Copier]","category":"page"},{"location":"95-reference/#BestieTemplate.BestieTemplate","page":"Reference","title":"BestieTemplate.BestieTemplate","text":"BestieTemplate.jl\n\nThis package defines a copier template for Julia packages and a basic user interface around copier to use it from Julia.\n\nThe main functions are: generate, apply, and update.\n\nTo create a new package using BestieTemplate run\n\njulia> BestieTemplate.generate(\"path/to/YourNewPackage.jl\")\n\nTo apply the template to an existing package\n\njulia> BestieTemplate.apply(\"path/to/YourExistingPackage.jl\")\n\nCheck the documentation: https://abelsiqueira.com/BestieTemplate.jl\n\n\n\n\n\n","category":"module"},{"location":"95-reference/#BestieTemplate._copy-Tuple{Any, Any, Any}","page":"Reference","title":"BestieTemplate._copy","text":"_copy(src_path, dst_path, data; kwargs...)\n\nInternal function to run common code for new or existing packages.\n\n\n\n\n\n","category":"method"},{"location":"95-reference/#BestieTemplate._read_data_from_existing_path-Tuple{Any}","page":"Reference","title":"BestieTemplate._read_data_from_existing_path","text":"data = _read_data_from_existing_path(dst_path)\n\nReads the destination folder to figure out some answers.\n\n\n\n\n\n","category":"method"},{"location":"95-reference/#BestieTemplate._sanitize_package_name-Tuple{Any}","page":"Reference","title":"BestieTemplate._sanitize_package_name","text":"package_name = _sanitize_package_name(path)\n\nSanitize the path to guess the package_name by looking at the base name and removing an extension. If the result is not a valid identifier, returns \"\".\n\n\n\n\n\n","category":"method"},{"location":"95-reference/#BestieTemplate.apply","page":"Reference","title":"BestieTemplate.apply","text":"apply(dst_path[, data]; kwargs...)\napply(src_path, dst_path[, data]; true, kwargs...)\n\nApplies the template to an existing project at path dst_path. If the dst_path does not exist, this will throw an error. For new packages, use BestieTemplate.generate instead.\n\nRuns the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.\n\nThe data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.\n\nKeyword arguments\n\nguess:Bool = true: Whether to try to guess some of the data from the package itself.\nwarn_existing_pkg::Bool = true: Whether to check if you actually meant update. If you run apply and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.\nquiet::Bool = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.\n\nThe other keyword arguments are passed directly to the internal Copier.copy.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.generate","page":"Reference","title":"BestieTemplate.generate","text":"generate(dst_path[, data]; kwargs...)\ngenerate(src_path, dst_path[, data]; true, kwargs...)\n\nGenerates a new project at the path dst_path using the template. If the dst_path already exists, this will throw an error, unless dst_path = \".\". For existing packages, use BestieTemplate.apply instead.\n\nRuns the copy command of copier with the BestieTemplate template. If src_path is not informed, the GitHub URL of BestieTemplate.jl is used.\n\nThe data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.\n\nKeyword arguments\n\nwarn_existing_pkg::Boolean = true: Whether to check if you actually meant update. If you run generate and the dst_path contains a .copier-answers.yml, it means that the copy was already made, so you might have means update instead. When true, a warning is shown and execution is stopped.\nquiet::Boolean = false: Whether to print greetings, info, and other messages. This keyword is also used by copier.\n\nThe other keyword arguments are passed directly to the internal Copier.copy.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.update","page":"Reference","title":"BestieTemplate.update","text":"update([data]; kwargs...)\nupdate(dst_path[, data]; kwargs...)\n\nRun the update command of copier, updating the dst_path (or the current path if omitted) with a new version of the template with a new version of the template.\n\nThe data argument is a dictionary of answers (values) to questions (keys) that can be used to bypass some of the interactive questions.\n\nKeyword arguments\n\nThe keyword arguments are passed directly to the internal Copier.update.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Copier","page":"Reference","title":"BestieTemplate.Copier","text":"Wrapper around copier.\n\nThere are three functions in this module:\n\ncopy\nrecopy\nupdate\n\n\n\n\n\n","category":"module"},{"location":"95-reference/#BestieTemplate.Copier.copy","page":"Reference","title":"BestieTemplate.Copier.copy","text":"copy(dst_path[, data]; kwargs...)\ncopy(src_path, dst_path[, data]; kwargs...)\n\nWrapper around copier.run_copy.\n\nThis is an internal function, if BestieTemplate's main API is not sufficient, open an issue. Note: this is not Base.copy, inside the Copier module we shadow that name.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Copier.recopy","page":"Reference","title":"BestieTemplate.Copier.recopy","text":"recopy(dst_path[, data]; kwargs...)\n\nWrapper around copier.run_recopy.\n\nThis is an internal function, if BestieTemplate's main API is not sufficient, open an issue.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Copier.update","page":"Reference","title":"BestieTemplate.Copier.update","text":"update(dst_path[, data]; kwargs...)\n\nWrapper around copier.run_update.\n\nThis is an internal function, if BestieTemplate's main API is not sufficient, open an issue.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#Debug-auto-docs","page":"Reference","title":"Debug auto docs","text":"","category":"section"},{"location":"95-reference/","page":"Reference","title":"Reference","text":"Modules = [BestieTemplate.Debug, BestieTemplate.Debug.Data]","category":"page"},{"location":"95-reference/#BestieTemplate.Debug","page":"Reference","title":"BestieTemplate.Debug","text":"Module Debug\n\nTools for debugging Bestie. Nothing here is public API.\n\nwarning: Warning\nThis file is not tested and not covered in codecov. Except for the data, it is not supposed to be used in the tests.\n\nNoteworthy: BestieTemplate.Debug.Data\n\n\n\n\n\n","category":"module"},{"location":"95-reference/#BestieTemplate.Debug.dbg_apply","page":"Reference","title":"BestieTemplate.Debug.dbg_apply","text":"dbg_apply([dst_path, data]; data_choice=:minimum)\n\nConvenience function to help debug apply. It runs apply with the dst_path destination and the given data (nothing by default).\n\nIt also uses a data_choice to determine fake starting data. This is passed to dbg_data.\n\nIt uses the pkgdir location of Bestie and adds the flags\n\ndefaults = true: Sent to copier to use the default answers.\nquiet = true: Low verbosity.\noverwrite = true: Overwrite all files.\nvcs_ref = HEAD: Use the development version of the template, including dirty repo changes.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Debug.dbg_data","page":"Reference","title":"BestieTemplate.Debug.dbg_data","text":"dbg_data(data_choice, more_data)\n\nReturns the fake debug data merged with more_data. The options for data_choice are:\n\n:nothing, :none: No random data.\n:required, :req: Only the required data is generated. You get asked which choice of optional data.\n:minimum, :min: The required data plus the choice \"minimum\" for optional data.\n:recommended, :rec: The required data plus the choice \"recommended\" for optional data.\n:ask: The required data plus the choice \"ask\". The optional questions will be asked.\n:ask_default: Same as :ask plus the default answers for the optional questions.\n:ask_and_say_no: Same as :ask plus answers no/false to the optional questions.\n:ask_and_say_yes: Same as :ask plus answers yes/true to the optional questions.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Debug.dbg_generate","page":"Reference","title":"BestieTemplate.Debug.dbg_generate","text":"dbg_generate([dst_path, data]; data_choice=:minimum)\n\nConvenience function to help debug generate. It runs generate with the dst_path destination (random by default) and the given data (nothing by default).\n\nIt also uses a data_choice to determine fake starting data. This is passed to dbg_data.\n\nIt uses the pkgdir location of Bestie and adds the flags\n\ndefaults = true: Sent to copier to use the default answers.\nquiet = true: Low verbosity.\nvcs_ref = HEAD: Use the development version of the template, including dirty repo changes.\n\n\n\n\n\n","category":"function"},{"location":"95-reference/#BestieTemplate.Debug.Data","page":"Reference","title":"BestieTemplate.Debug.Data","text":"Fake data for testing\n\nDebug.Data: NamedTuple of Dictionaries with default data\nDebug.Data.required: Required data if you use defaults = true\nDebug.Data.strategy_minimum: Required data for strategy minimum, no defaults.\nDebug.Data.strategy_recommended: Required data for strategy recommended, no defaults.\nDebug.Data.strategy_ask: Required data for strategy ask, no defaults.\n\n\n\n\n\n","category":"module"},{"location":"90-contributing/#contributing","page":"Contributing guidelines","title":"Contributing guidelines","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"First of all, thanks for the interest!","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"We welcome all kinds of contribution, including, but not limited to code, documentation, examples, configuration, issue creating, etc.","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"Be polite and respectful, and follow the code of conduct.","category":"page"},{"location":"90-contributing/#Bug-reports-and-discussions","page":"Contributing guidelines","title":"Bug reports and discussions","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If you think you found a bug, feel free to open an issue. Focused suggestions and requests can also be opened as issues. Before opening a pull request, start an issue or a discussion on the topic, please.","category":"page"},{"location":"90-contributing/#Working-on-an-issue","page":"Contributing guidelines","title":"Working on an issue","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If you found an issue that interests you, comment on that issue what your plans are. If the solution to the issue is clear, you can immediately create a pull request (see below). Otherwise, say what your proposed solution is and wait for a discussion around it.","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"tip: Tip\nFeel free to ping us after a few days if there are no responses.","category":"page"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If your solution involves code (or something that requires running the package locally), check the developer documentation. Otherwise, you can use the GitHub interface directly to create your pull request.","category":"page"},{"location":"90-contributing/#Additions-and-modifications-to-the-template","page":"Contributing guidelines","title":"Additions and modifications to the template","text":"","category":"section"},{"location":"90-contributing/","page":"Contributing guidelines","title":"Contributing guidelines","text":"If you have any new idea or think the template needs to be updated or fixed, please search our issues and if there isn't anything relevant, open a new issue.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"CurrentModule = BestieTemplate","category":"page"},{"location":"#BestieTemplate-Your-best-practices-friend","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"(Image: BestieTemplate.jl)","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"Welcome to the documentation of BestieTemplate.jl. This package provides a template in the copier engine for a Julia package. Furthermore, it provides a wrapper around convenience calls to that package.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"The main features of this package/template are:","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"It provides a curated (opinionated) list of tools and best practices for Julia package development;\nIt can be applied and reapplied to existing packages, allowing the updates in the template to be imported into the package;","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"(Image: asciicast)","category":"page"},{"location":"#Using","page":"BestieTemplate - Your best practices friend","title":"Using","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"To fully benefit from the template, there are some steps to be done before and after you generate your package. Check the full guide for more details.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"However, if you kinda know what you need to do, this is the TL;DR:","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"using> # press ]\npkg> add BestieTemplate\njulia> using BestieTemplate\njulia> BestieTemplate.generate(\"path/to/YourNewPackage.jl\")\njulia> # or BestieTemplate.apply(\"path/to/YourExistingPackage.jl\")","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"I really recommend checking the full guide, though.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"To understand more about our motivation and what the template provides, check the explanation page.","category":"page"},{"location":"#Getting-and-providing-help","page":"BestieTemplate - Your best practices friend","title":"Getting and providing help","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"I hope you find this package useful. If you have any questions, requests, or comments, check the issues and discussion pages.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"If you would like to get involved in the BestieTemplate growth, please check our contributing guide. We welcome contributions of many types, including coding, reviewing, creating issues, creating tutorials, interacting with users, etc. Make sure to follow our code of conduct.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"If your interest is in developing the package, check the development guide as well.","category":"page"},{"location":"#References","page":"BestieTemplate - Your best practices friend","title":"References","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"Here is a list of links/repos that include content that we have used for inspiration, or used directly. This is most likely not a complete list, since many of the things included here were based on existing packages and knowledge that we brought from other projects. This also doesn't explain where each file came from or why they are here. You can find some of that information in the Explanation section of the docs.","category":"page"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"PkgTemplates.jl, naturally. We used it for many years, and in particular for the initial TulipaEnergyModel.jl commit (see below).\nNetherlands eScience Center's python template includes many of the best practices that we apply here. We used many of the ideas there in a Julia context, and took many non-Julia specific ideas from there.\nTulipaEnergyModel.jl was the project that motivated this version of a template. From the start we decide to implement many best practices and so we started from a PkgTemplates.jl template and started adding parts of the python template that made sense.\nThe Julia Smooth Optimizers package ecosystem was one of the main motivations to look for a solution that could be applied and reapplied to existing packages, in particular to help maintainers.","category":"page"},{"location":"#Contributors","page":"BestieTemplate - Your best practices friend","title":"Contributors","text":"","category":"section"},{"location":"","page":"BestieTemplate - Your best practices friend","title":"BestieTemplate - Your best practices friend","text":"\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\"Abel
Abel Soares Siqueira

💻 📆 📖 🚧
\"Tangi
Tangi Migot

💻 📖 👀
\"Pablo
Pablo Rodríguez-Sánchez

📖 🤔
\"Olga
Olga Lyashevska

💻 📖 🤔
\"Luisa
Luisa Orozco

💻 📖 🤔
\"Netherlands
Netherlands eScience Center

💵
\"Suvayu
Suvayu Ali

🐛 👀 💻
\"Stefan
Stefan Verhoeven

💻 🤔
\"Dominique\"/
Dominique

🤔 💻
\"fdiblen\"/
fdiblen

💻 👀
\"Greg
Greg Neustroev

💻
\"Luca
Luca Ferranti

🤔
\"Guillaume
Guillaume Dalle

🤔
\"Johannes
Johannes Hidding

🐛 👀
\"Frames
Frames White

💻 🐛 🤔
\n\n\n\n\n\n","category":"page"},{"location":"10-full-guide/#full_guide","page":"Full guide","title":"Full guide","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Welcome to full usage guide of BestieTemplate.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Pages = [\"10-full-guide.md\"]\nDepth = 2:3","category":"page"},{"location":"10-full-guide/#Before-installing","page":"Full guide","title":"Before installing","text":"","category":"section"},{"location":"10-full-guide/#Things-to-know","page":"Full guide","title":"Things to know","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"This template is an attempt to provide many best practices to package development. This can be overwhelming, so you might prefer to take it easy at first and install only the fewest amount of new things possible.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Thinking of you, the first optional question in the template is how to deal with the optional questions:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The \"Recommended\" option lets us select the best practices that we like the most. This means \"yes\" to most of the optional answers.\nThe \"Minimum\" option does not add any optional feature. Your package will still be a valid Julia package with a few things that we deem essential (such as online testing, documentation, and CITATION.CFF).","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The \"Minimum\" option is still a step above the bare minimum for a Julia package, so you will still benefit from the template. The \"Recommended\" option adds many features that package maintainers might find useful in the long run, but might be too much at once. Check the Explanation page for more information.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you decide to gradually adopt, do this:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Follow the relevant application section for New or Existing.\nRemember to select the \"Minimum\" optional questions.\nFollow the Update section, change your answer from \"Minimum\" to \"Recommended\" or \"Ask me\".","category":"page"},{"location":"10-full-guide/#Things-to-install","page":"Full guide","title":"Things to install","text":"","category":"section"},{"location":"10-full-guide/#EditorConfig","page":"Full guide","title":"EditorConfig","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Install a plugin on your editor to use EditorConfig. This will ensure that your editor is configured with important formatting settings.","category":"page"},{"location":"10-full-guide/#pre-commit","page":"Full guide","title":"pre-commit","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"We recommend using https://pre-commit.com to run linters and formatters. If you select the \"recommended\" options later on, you will need pre-commit installed.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"pre-commit is a python package, so there are a few ways to install. We like one of these two ways:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Using pipx as follows:\npipx install pre-commit\nUsing pip in a virtual environment\npython -m venv env\nsource env/bin/activate\npip install pre-commit","category":"page"},{"location":"10-full-guide/#JuliaFormatter","page":"Full guide","title":"JuliaFormatter","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"When using pre-commit, the Julia code is formatted using JuliaFormatter.jl, so please install it globally first:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> # Press ]\npkg> activate\npkg> add JuliaFormatter","category":"page"},{"location":"10-full-guide/#Install-BestieTemplate-(or-copier)","page":"Full guide","title":"Install BestieTemplate (or copier)","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"To use the template, we recommend installing the package BestieTemplate.jl globally:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> # press ]\npkg> activate\npkg> add BestieTemplate","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The BestieTemplate package wraps copier and adds some lightweight checks and parameters to make your user experience better.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Alternative\nAlternatively, you can use copier directly, in which case you will have the pure template generation experience. If that is the case, I will assume that you know what you are doing and won't show the full command here to avoid confusing new users.","category":"page"},{"location":"10-full-guide/#Using-the-template","page":"Full guide","title":"Using the template","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"There are three use cases on using the template:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You are using the template to start a new package.\nYou already have a Julia project and you want to apply the template to your project.\nYou already uses the template and you want to update to get the latest changes.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The three cases are listed below.","category":"page"},{"location":"10-full-guide/#new_package","page":"Full guide","title":"New package","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Simply run","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> using BestieTemplate\njulia> BestieTemplate.generate(\"full/path/to/YourPackage.jl\")","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"This will create the folder at the given path and create a package named YourPackage using the latest release of the BestieTemplate. You will be prompted with many questions, some required and some with our recommended choices.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You can give more options to the generate function, including the source of the template, pre-filled data, and options passed to the underlying project generator copier. See the full docstring for BestieTemplate.generate for more information.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The resulting folder will not be a git package yet (to avoid trust issues), so you need to handle that yourself. You should see a short guide on screen, but here it is again:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"cd full/path/to/YourPackage.jl\ngit init\ngit add .\npre-commit run -a # Try to fix possible pre-commit issues (failures are expected)\ngit add .\ngit commit -m \"First commit\"\npre-commit install # Future commits can't be directly to main unless you use -n","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Now, create a new repository on GitHub and push your code. We won't give you details on how to do this, but you can check The Turing Way.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"After that, jump on to Setting up your package.","category":"page"},{"location":"10-full-guide/#existing_package","page":"Full guide","title":"Applying to an existing package","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"To apply the template to an existing package, you can do the following:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: git\nThis assumes that you already use git on that package and the your working directory is clean. It will fail otherwise.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> using BestieTemplate\njulia> BestieTemplate.apply(\"full/path/to/YourPackage.jl\")","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"This command will look around your project path and try to guess some of the answers. Currently, we guess:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"PackageName and PackageUUID from the name and uuid fields in Project.toml,\nAuthors from the authors field in Project.toml,\nPackageOwner from the repo in docs/make.jl,\nJuliaMinVersion from the compat section in Project.toml,\nIndentation from the indent field in .JuliaFormatter.toml.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"tip: Overwrite\nYou will be asked whether to overwrite existing files or not. Since you are using git, you can try it out and reset if you don't like the result. So we recommend overwriting at this point.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you don't like the result, or want to override the answers, you can run the apply function with additional arguments, for instance:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> data = Dict(\"Authors\" => \"Bob \")\njulia> BestieTemplate.apply(\"full/path/to/YourPackage.jl\", data)","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Alternatively, you can also tell Bestie to not guess:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> BestieTemplate.apply(\"full/path/to/YourPackage.jl\"; guess = false)","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"See the full docstring for BestieTemplate.apply for more information.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Review the changes\nDon't just add the changes blindly, because some of your files can and will be overwritten.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: README.md conflicts\nWe really can't avoid some conflicts, and although some file can be skipped if existing (such as CITATION.cff), some can't. For instance, README.md will most likely be wrong when you apply the template, but the badges (for instance), need to be included in your project. This means that README.md cannot be skipped, and you will have to accept the overwrite and manually fix your README.md.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"tip: Formatting\nYou might most likely see changes in the formatting. So if you have a formatter, it might be best to run it before reviewing the changes. If you have chosen the \"Recommended\" answers, or explicitly chose to add pre-commit, then you should use it now (see below).","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you need some help with undoing some of these changes, I recommend using a graphical interface for git. After the template is applied and you are happy with the conflict resolution, enable pre-commit and push your code.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"git add .\npre-commit run -a # Try to fix possible pre-commit issues (failures are expected)\npre-commit install # All commits will run pre-commit now\ngit add .\ngit commit -m \"Apply BestieTemplate vx.y.z\"","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Push your code to GitHub and head to Setting up your package for information on what to do next.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Now, go to Setting up your package to check what you still need to configure for your package.","category":"page"},{"location":"10-full-guide/#updating_package","page":"Full guide","title":"Updating","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"To update the package, simply call","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"julia> BestieTemplate.update()","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You will be asked the relevant questions of the package as if you had applied it. The big differences are:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"It will only apply the things that are new since you last applied/updated\nIt will remember previous answer.\nIt will overwrite without asking.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"tip: Change previous answers\nYou can change your previous answers. In other words, if you though something was not mature enough in the past, but you are more confident in that now, you can adopt it now. This works even if the template was not updated itself.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"As with the first application, you need to run pre-commit run -a to fix the unavoidable linting and formatting issues. Check the modifications in the relevant linter and formatting files, if you changed them manually, before doing it, though.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"pre-commit run -a","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You will possibly have conflicts when you apply the template - i.e., updates to the template that conflicts with changes that you've made to the package. Whenever a conflict appears, you will need to decide on whether to accept or reject the new changes. Fix the conflicts using git.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The underlying package copier will use git to apply the differences and it will overwrite whatever files it finds in the way. Since git is mandatory, the changes will be left for you to review.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Review the changes\nI repeat, the changes will be left for you to review. Don't just add them blindly, because some of your modifications can and will be overwritten.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you need some help with undoing some of these changes, I recommend using a graphical interface to git.","category":"page"},{"location":"10-full-guide/#Setting-up-your-package","page":"Full guide","title":"Setting up your package","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"There are various steps to setting up your package on GitHub. Some are important now, and some will be relevant when you try to make your first release.","category":"page"},{"location":"10-full-guide/#Add-to-GitHub","page":"Full guide","title":"Add to GitHub","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you haven't yet, create a repo on GitHub and push your code to it.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"info: Info\nThe actions will run and you will see errors in the documentation and linting. Do not despair.","category":"page"},{"location":"10-full-guide/#Documentation","page":"Full guide","title":"Documentation","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Go to your package setting on Github and find the \"Actions\" tab, the \"General\" link. On that page, find the \"Workflow permissions\" and change the selection to \"Read and write permissions\", and enable \"Allow GitHub Actions can create and approve pull requests\". This will allow the documentation workflow to work for development.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Go to the Actions page, click the failing Docs workflow and click on \"re-run all jobs\". It should pass now.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Now, go to your package setting on GitHub and find the \"Pages\" link. You should see an option to set the Source to \"Deploy from a branch\", and select the branch to be \"gh-pages\" and to deploy from the \"/ (root)\".","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"After circa 1 minute, you can check that the documentation was built properly.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"info: Info\nAt this point, you should have passing workflows.Tests should have been passing from the start.\nLint was fixed when we pushed the code to GitHub.\nDocs was fixed with the permissions change.","category":"page"},{"location":"10-full-guide/#Documentation-for-releases","page":"Full guide","title":"Documentation for releases","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"info: Info\nThis section is only relevant when making your first release, but it might be better to get it out of the way now.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You need to set a DOCUMENTER_KEY to build the documentation from the tags automatically when using TagBot (which we do by default). Do the following:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"pkg> activate --temp\npkg> add DocumenterTools\njulia> using DocumenterTools\njulia> DocumenterTools.genkeys(user=\"UserName\", repo=\"PackageName.jl\")","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Follow the instruction in the terminal.","category":"page"},{"location":"10-full-guide/#Enable-Codecov-for-code-coverage","page":"Full guide","title":"Enable Codecov for code coverage","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you don't have a Codecov account, go to https://codecov.io and create one now. After creating an account and logging in, you will see your main page with a list of your packages. Select the one that you are creating, it will open a configuration page.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"On the configuration page, select \"Using GitHub Actions\" as your CI. The first step in the list given you the CODECOV_TOKEN. Click on the \"repository secret\" link on that page. It should lead you to the GitHub settings > secrets and variables > actions, under a \"New secret\" screen. Write CODECOV_TOKEN on the \"Name\" field and paste the token that you see on codecov on the \"Secret\" field. Click \"Add secret\".","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Step 2 is not necessary because it is already present in the template.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"The next time that the tests are run, the coverage page will be updated, and the badge will be fixed.","category":"page"},{"location":"10-full-guide/#Add-key-for-Copier.yml-workflow","page":"Full guide","title":"Add key for Copier.yml workflow","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Copier.yml is work in progress\nThis option is not selected by default because it is a work in progress. If you want to use it, you have to pass the key \"AddCopierCI\" => true to the data argument of generate or apply, or select \"Ask me\" when deciding how to answer the optional questions.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"You can reapply the template in the future. This is normally a manual job, specially because normally there are conflicts. That being said, we are experimenting with having a workflow that automatically checks whether there are updates to the template and reapplies it. A Pull Request is created with the result.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"warning: Warning\nThis is optional, and in development, so you might want to delete the workflow instead.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"If you decide to use, here are the steps to set it up:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Create a Personal Access Token to be used by the Copier workflow.\nGo to https://github.com/settings/tokens.\nCreate a token with \"Content\", \"Pull-request\", and \"Workflows\" permissions.\nCopy the Token.\nGo to your YOUR_PACKAGE_URL/settings/secrets/actions.\nCreate a \"New repository secret\" named COPIER_PAT.","category":"page"},{"location":"10-full-guide/#CITATION.cff-and-Zenodo-deposition","page":"Full guide","title":"CITATION.cff and Zenodo deposition","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Update your CITATION.cff file with correct information. You can use cffinit to generate it easily.","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Before releasing, enable Zenodo integration at https://zenodo.org/account/settings/github/ to automatically generate a deposition of your package, i.e., archive a version on Zenodo and generate a DOI.","category":"page"},{"location":"10-full-guide/#Update-README.md","page":"Full guide","title":"Update README.md","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Update the badges\nAdd a description","category":"page"},{"location":"10-full-guide/#Enable-discussions","page":"Full guide","title":"Enable discussions","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Enable GitHub discussions.","category":"page"},{"location":"10-full-guide/#First-release","page":"Full guide","title":"First release","text":"","category":"section"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"When you are ready to make your first release, enable the Julia Registrator bot. Make sure that you haven't skipped these sections:","category":"page"},{"location":"10-full-guide/","page":"Full guide","title":"Full guide","text":"Documentation for releases\nCITATION.cff and Zenodo deposition","category":"page"}] }