Skip to content

Commit

Permalink
List questions in the documentation
Browse files Browse the repository at this point in the history
Add a new field to the copier questions: description.
This is not picked up by copier, it is only used in the new docs
page, 30-questions.
Adds a new documentation page 30-questions. This lists the
questions and the new description.
Changes the strategy question to include a link to the questions.

Closes #274
  • Loading branch information
abelsiqueira committed Sep 9, 2024
1 parent c46df89 commit 44c68f6
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 7 deletions.
21 changes: 21 additions & 0 deletions copier/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,54 @@ JuliaMinCIVersion:
type: str
help: Minimum Julia version used in the tests (lts defaults to the Long Term Support version)
default: "{% if JuliaMinVersion == JULIA_LTS_VERSION %}lts{% else %}{{ JuliaMinVersion }}{% endif %}"
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.
AddMacToCI:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
help: MacOS CI test (Package tests run on Ubuntu latest. Do you want to add macOS latest as well?)
default: "{{ AnswerStrategy != 'minimum' }}"
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:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
help: Windows CI test (Same as above, but for Windows)
default: "{{ AnswerStrategy != 'minimum' }}"
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.
RunJuliaNightlyOnCI:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
help: 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?)
default: false
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.
UseCirrusCI:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
help: FreeBSD CI test with CirrusCI (Add CirrusCI to run the package tests on FreeBSD?)
default: false
description: |
Controls whether to add a `.cirrus.yml` to run tests on the Cirrus CI platform for the FreeBSD Operating System.
Defaults to no.
AddCopierCI:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
help: 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)
default: false
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.
11 changes: 11 additions & 0 deletions copier/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@ AddPrecommit:
type: bool
default: "{{ AnswerStrategy != 'minimum' }}"
help: 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:
- Formatters: Not only JuliaFormatter, but also formatters for Markdown, TOML, YAML, and JSON files.
- Linters: Analyze the code to prevent "bad" things. Sometimes includes formatting rules, but frequently useful for what falls outside formatting, but leads to poor code performance or possible pitfalls. In Julia, JET would be a candidate for this, although we don't have any Julia linters in the pre-commit hooks (yet).
- Quality of Life checks: Prevents commits if you have `.rej` files, if you are on the main branch, if you forget a git merge marker, etc.
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:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
default: "{{ AnswerStrategy != 'minimum' }}"
help: 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 `@testset`s.
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.
21 changes: 20 additions & 1 deletion copier/community.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,46 @@ AddContributionDocs:
type: bool
default: "{{ AnswerStrategy != 'minimum' }}"
help: 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:
- `90-contributing.md` is aimed at anyone interested in contributing to the project. It provides general guidelines on how to communicate and where to find help.
- `91-developer.md` is aimed at code contributors. It provides more focused information for people that will need to clone the package to contribute to it, such as branching guidelines, pre-commit installation, building documentation, and making a new release.
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:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
default: "{{ AnswerStrategy != 'minimum' }}"
help: Add allcontributors (all-contributors.org is a project that adds collaborators information in the README and the docs)
help: 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](https://allcontributors.org).
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:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
default: "{{ AnswerStrategy != 'minimum' }}"
help: Code of conduct file (Add a CODE_OF_CONDUCT.md file from Contributor Covenant?)
description: |
This uses version 2.1 of the [Contributor Covenant](https://www.contributor-covenant.org) code of conduct.
Defaults to yes for the recommended strategy, or no otherwise.
CodeOfConductContact:
when: "{{ AddCodeOfConduct }}"
type: str
help: Contact person/entity listed in the CODE_OF_CONDUCT.md file (Will be listed as contact to enforce the code of conduct, if necessary)
default: "{{ Authors.split(',')[0] | regex_replace('.*<(.*)>.*', '\\\\1') }}"
description: |
This is the contact person or entity for enforcement of the code of conduct. It will be added to the CODE_OF_CONDUCT file, in a section titled "Enforcement".
Defaults to the first authors' e-mail using a Regex substitution from the `Authors` question.
AddGitHubTemplates:
when: "{{ AnswerStrategy == 'ask' }}"
type: bool
default: "{{ AnswerStrategy != 'minimum' }}"
help: 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.
61 changes: 58 additions & 3 deletions copier/essential.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,75 @@ PackageName:
{% if not (PackageName | regex_search('^[A-Z][A-z0-9]*$')) %}
Must start with a capital letter, and use letters or numbers only
{% endif %}
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:
type: str
help: UUID (For existing packages, copy the UUID from Project.toml, otherwise use the one generated below)
validator: "{% if PackageUUID | length == 0 %}Can't be empty{% endif %}"
default: "{{ 999999999999999999999999999999999 | ans_random | to_uuid }}"
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:
type: str
help: GitHub username or organization that owns the package (This will be used for URLs)
validator: "{% if PackageOwner | length == 0 %}Can't be empty{% endif %}"
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:
when: false
type: str
help: (Deprecated in 0.10.0) Name of the package author (Used to kickstart a few files)
validator: "{% if AuthorName | length == 0 %}Can't be empty{% endif %}"
description: |
!!! warning Deprecated
AuthorName has been replaced by Authors.
Defines the name of the author.
AuthorEmail:
when: false
type: str
help: (Deprecated in 0.10.0) E-mail of the package author (Used to kickstart a few files)
validator: "{% if AuthorEmail | length == 0 %}Can't be empty{% endif %}"
description: |
!!! warning Deprecated
AuthorEmail has been replaced by Authors.
Defines the e-mail of the author.
Authors:
type: str
help: Package authors separated by commas (We recommend the form AUTHOR <EMAIL>, but this can be ignored)
placeholder: AUTHOR <EMAIL>,AUTHOR <EMAIL>
help: Package authors separated by commas (We recommend the form NAME <EMAIL>, but this can be ignored)
placeholder: NAME <EMAIL>,NAME <EMAIL>
default: "{% if AuthorName | length > 0 %}{{ AuthorName }} <{{ AuthorEmail }}> and contributors{% endif %}"
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.
JuliaMinVersion:
type: str
help: Minimum Julia version (Used in Project.toml and CI. The suggestion below is the LTS version)
help: Minimum Julia version (Used in Project.toml. The suggestion below is the LTS version)
default: "{{ JULIA_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.
License:
type: str
Expand All @@ -52,15 +87,35 @@ License:
- MIT
- MPL-2.0
default: MIT
description: |
Multiple choice question to select a License.
Defaults to the MIT License, which is the most common choice for Julia packages.
LicenseCopyrightHolders:
type: str
help: License Copyright Holders (Added in front of "Copyright (c) " notices, when applicable)
default: "{{ Authors | regex_replace('\\s*([^,]*)\\s*<[^,]*>[^,]*', '\\\\1') | regex_replace('\\s*,\\s*', ', ') | trim }}"
validator: "{% if LicenseCopyrightHolders | length == 0%}Can't be empty{% endif %}"
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:
type: int
help: Indentation length (Used in .JuliaFormatter and other configuration files of formatters and linters if you add them)
validator: "{% if Indentation <= 0 %}Indentation must be positive{% endif %}"
default: 4
description: |
The number of spaces that define an indentation level.
This is used in many configuration files:
- `.JuliaFormatter.toml`: To control indentation in Julia;
- `.editorconfig`: To suggest indentation in many languages;
- `.markdownlint.json`: To control indentation in Markdown;
- `.pre-commit-config.yml`: In the hook `pretty-format-json` to control the indentation of JSON files.
- `.yamllint.yml`: To control indentation in YAML 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.
9 changes: 8 additions & 1 deletion copier/strategy.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
AnswerStrategy:
type: str
default: recommended
help: Optional questions (You can use our defaults, or the bare minimum, or decide everything)
help: "Strategy for optional questions (You can see the full list of questions in https://abelsiqueira.com/BestieTemplate.jl/dev/30-questions/)"
choices:
Recommended (Our defaults): "recommended"
Minimum (Answer no to any addition): "minimum"
Ask me (Ask all questions): "ask"
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.
3 changes: 2 additions & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[deps]
BestieTemplate = "E5D671A7-4186-4F1A-BF88-C19B630DA94F"
BestieTemplate = "e5d671a7-4186-4f1a-bf88-c19b630da94f"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"

[compat]
Documenter = "1"
6 changes: 5 additions & 1 deletion docs/src/20-explanation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
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](@ref) page.

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

Expand Down Expand Up @@ -104,7 +106,9 @@ These are neither recommended nor part of the minimum template, which means that

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

- It is a best practices, but for a niche audience (e.g., `.cirrus.yml` for testing on FreeBSD);
- 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](@ref).

### Basic package structure

Expand Down
85 changes: 85 additions & 0 deletions docs/src/30-questions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Questions

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.

To answer any of these question via the Julia interface, you can pass a dictionary to the `generate` or `apply` functions.
For instance:

```@example
using BestieTemplate
cd(mktempdir()) do # hide
data = Dict(
"PackageName" => "NotMyPkg",
"PackageOwner" => "bestie",
"Authors" => "Bestie",
)
BestieTemplate.generate(
pkgdir(BestieTemplate), # hide
"MyPkg",
data,
defaults=true, # Choose default for other questions - will fail if there is none
quiet=true,
vcs_ref="HEAD", # hide
)
print(read("MyPkg/Project.toml", String))
end # hide
```

!!! note "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.

```@eval
using Markdown, YAML
sections = String[]
questions = Dict{String,Any}()
dir = joinpath(@__DIR__, "..", "..")
out = ""
for line in readlines(joinpath(dir, "copier.yml"))
if startswith("!include")(line)
file = split(line)[2]
section_name = basename(file) |> x -> splitext(x)[1]
if section_name == "constants"
continue
end
push!(sections, section_name)
yaml = YAML.load_file(joinpath(dir, file))
questions[section_name] = yaml
end
end
title_override = Dict(
"ci" => "Continuous Integration",
)
titles = Dict(
section => get(title_override, section, section) |> x -> replace(x, "-" => " ") |> titlecase
for section in sections
)
for section in sections
global out
title = titles[section]
out *= "## Section: $title\n\n"
for question in questions[section]
name, answers = question
out *= "### $name\n\n"
help = answers["help"]
out *= "**Question (in the CLI)**: $help\n\n"
description = get(answers, "description", "")
if description != ""
out *= "**Description:**\n"
out *= join("> " .* split(description, "\n"), "\n>\n")
end
out *= "\n\n"
end
end
Markdown.parse(out)
```
1 change: 1 addition & 0 deletions docs/src/91-developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ Follow the other questions style and syntax. The gist of it is that you need:
- A `help: Short description or title (Longer description and details)`.
- A `default`, if the question is optional.
- To default to `true` if "Recommended" or `false` for "Minimum", use `{{ AnswerStrategy != 'minimum' }}`.
- A `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](@ref)).

### Dependent sections in a file

Expand Down

0 comments on commit 44c68f6

Please sign in to comment.