Developer documentation
If you haven't, please read the Contributing guidelines first.
If you want to make contributions to this package that involves code, then this guide is for you.
First time clone
If you have writing rights, you don't have to fork. Instead, simply clone and skip ahead. Whenever upstream is mentioned, use origin instead.
If this is the first time you work with this repository, follow the instructions below to clone the repository.
Fork this repo
Clone your repo (this will create a
git remote
calledorigin
)Add this repo as a remote:
git remote add upstream https://github.com/abelsiqueira/COPIERTemplate.jl
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
.
Linting and formatting
Install a plugin on your editor to use EditorConfig. This will ensure that your editor is configured with important formatting settings.
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:
julia> # Press ]
pkg> activate
pkg> add JuliaFormatter
To install pre-commit
, we recommend using pipx as follows:
# Install pipx following the link
pipx install pre-commit
With pre-commit
installed, activate it as a pre-commit hook:
pre-commit install
To run the linting and formatting manually, enter the command below:
pre-commit run -a
Now, you can only commit if all the pre-commit tests pass.
Testing
As with most Julia packages, you can just open Julia in the repository folder, activate the environment, and run test
:
julia> # press ]
pkg> activate .
pkg> test
Testing local changes to the template
I recommend installing copier, although it is possible to test the template using only Julia, it becomes more complicated, and cumbersome. Using pipx
(as above), you can just run
pipx install copier
To test your local modifications, you can run copier with the --vcs-ref HEAD
flag and point to your local clone. This will use the latest changes, including uncommitted modifications (i.e., the dirty state). What I normally do is this:
cd $(mktemp -d) # Go to a tmp folder
copier copy --vcs-ref HEAD /path/to/clone/ pkg # Clone dirty clone into pkg
Working on a new issue
We try to keep a linear history in this repo, so it is important to keep your branches up-to-date.
Fetch from the remote and fast-forward your local main
git fetch upstream git switch main git merge --ff-only upstream/main
Branch from
main
to address the issue (see below for naming)git switch -c 42-add-answer-universe
Push the new local branch to your personal remote repository
git push -u origin 42-add-answer-universe
Create a pull request to merge your remote branch into the org main.
Branch naming
- If there is an associated issue, add the issue number.
- If 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.
- If the changes are not small and there is no associated issue, then create the issue first, so we can properly discuss the changes.
- Use dash separated imperative wording related to the issue (e.g.,
14-add-tests
,15-fix-model
,16-remove-obsolete-files
).
Commit message
- Use imperative or present tense, for instance: Add feature or Fix bug.
- Have informative titles.
- When necessary, add a body with details.
- If there are breaking changes, add the information to the commit message.
Before creating a pull request
Try to create "atomic git commits" (recommended reading: The Utopic Git History).
Make sure the tests pass.
Make sure the pre-commit tests pass.
Fetch any
main
updates from upstream and rebase your branch, if necessary:git fetch upstream git rebase upstream/main BRANCH_NAME
Then you can open a pull request and work with the reviewer to address any issues.
Building and viewing the documentation locally
Following the latest suggestions, we recommend using LiveServer
to build the documentation. Here is how you do it:
- Run
julia --project=docs
to open Julia in the environment of the docs. - If this is the first time building the docs
- Press
]
to enterpkg
mode - Run
pkg> dev .
to use the development version of your package - Press backspace to leave
pkg
mode
- Press
- Run
julia> using LiveServer
- Run
julia> servedocs()
Making a new release
To create a new release, you can follow these simple steps:
- Create a branch
release-x.y.z
- Update
version
inProject.toml
- Update the
CHANGELOG.md
:- Rename the section "Unreleased" to "[x.y.z] - yyyy-mm-dd" (i.e., version under brackets, dash, and date in ISO format)
- Add a new section on top of it named "Unreleased"
- Add a new link in the bottom for version "x.y.z"
- Change the "[unreleased]" link to use the latest version - end of line,
vx.y.z ... HEAD
.
- Create a commit "Release vx.y.z", push, create a PR, wait for it to pass, merge the PR.
- Go back to main screen and click on the latest commit (link: https://github.com/abelsiqueira/COPIERTemplate.jl/commit/main)
- At the bottom, write
@JuliaRegistrator register
After that, you only need to wait and verify:
- Wait for the bot to comment (should take < 1m) with a link to a RP to the registry
- Follow the link and wait for a comment on the auto-merge
- The comment should said all is well and auto-merge should occur shortly
- After the merge happens, TagBot will trigger and create a new GitHub tag. Check on https://github.com/abelsiqueira/COPIERTemplate.jl/releases
- After the release is create, a "docs" GitHub action will start for the tag.
- After it passes, a deploy action will run.
- After that runs, the stable docs should be updated. Check them and look for the version number.
Additions to the templates
This 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.
Creating a new question
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.
Follow the other questions style and syntax. The gist of it is that you need:
- A
CamelCase
name. when: "{{ AnswerStrategy == 'ask' }}"
if the question is optional.- A
type
. - A
help: Short description or title (Longer description and details)
. - A
default
, if the question is optional.- To default to
true
if "Recommended" orfalse
for "Minimum", use{{ AnswerStrategy != 'minimum' }}
.
- To default to
Dependent sections in a file
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
{% if AddSomeStuff %}
...
{% endif %}
AddSomeStuff
is assumed to be boolean here, but you can use other conditions, such as {% if PackageName == 'Pkg' %}
.
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.
# Good
- Alice{% if AddBob %}
- Bob{% endif}
- Carlos
- Diana
While the code below will parse into two lists of one and two elements, respectively:
# Bad
- 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 %}