CompatHelper
CompatHelper is a Julia package that helps you keep your [compat]
entries up-to-date.
Whenever one of your package's dependencies releases a new version, CompatHelper opens a pull request on your repository that modifies your [compat]
entry to reflect the newly released version.
Table of Contents
- 1. Installation
- 2. Configuration options
- 3. Troubleshooting
- 4. Self-hosting and other environments
- 5. Acknowledgements
1. Installation
1.1 Create the workflow file (required)
Create a file at .github/workflows/CompatHelper.yml
with the following contents:
name: CompatHelper
on:
schedule:
- cron: '00 00 * * *'
workflow_dispatch:
jobs:
CompatHelper:
runs-on: ubuntu-latest
steps:
- name: Pkg.add("CompatHelper")
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }} # optional
run: julia -e 'using CompatHelper; CompatHelper.main()'
CompatHelper is now installed as a GitHub Action on your repository. But wait: do you fall into any of the following categories:
- You use GitHub Actions to test your package using continuous integration (CI).
- You use GitHub Actions to build and deploy the documentation for your package.
If you do not fall into any of those categories, then you are done! There is nothing more that you need to do.
But if you do fall into one or more of those categories, then you also need to set up an SSH deploy key for CompatHelper to use. Read on:
1.2. Set up the SSH deploy key (optional)
Note: if you already have an SSH deploy key set up in a secret, e.g. DOCUMENTER_KEY
or FRANKLIN_PRIV
, you can reuse it. See the "Advanced notes" section below.
1.2.1. Motivation
The default CompatHelper setup has one flaw: the pull requests that CompatHelper opens will not trigger any other GitHub Actions.
Consider the following situations:
- You use GitHub Actions to test your package using continuous integration (CI).
- You use GitHub Actions to build and deploy the documentation for your package.
If any of those situations apply to you, then you will need to set up an SSH deploy key for CompatHelper. Once you have set up an SSH deploy key for CompatHelper, the pull requests that CompatHelper opens will trigger all of the usual GitHub Actions.
If none of those situations apply to you, then you don't need to set up an SSH deploy key for CompatHelper.
1.2.2. Instructions for setting up the SSH deploy key
It is easy to set up an SSH deploy key for CompatHelper. Here are the instructions:
ssh-keygen -N "" -f compathelper_key
cat compathelper_key # This is the private key. Copy this to your clipboard.
- Go to the GitHub page for your package's repository, click on the Settings tab, then click on Secrets, and then click on Add new secret. Name the secret
COMPATHELPER_PRIV
. For the contents, paste in the private key that you copied in the previous step. cat compathelper_key.pub # This is the public key. Copy this to your clipboard.
- Go to the GitHub page for your package's repository, click on the Settings tab, then click on Deploy keys, and then click on Add deploy key. Name the deploy key
COMPATHELPER_PUB
. For the contents, paste in the public key that you copied in the previous step. Make sure that you give the key write access. rm -f compathelper_key compathelper_key.pub
1.2.3. Advanced notes
When you supply the private key, you can either provide the raw private key itself (as we did above), or you can provide the Base64-encoded form of the private key.
For example, if you already have a Base64-encoded private key saved as a secret, you can re-use it. If e.g. the secret is named DOCUMENTER_KEY
, then simply replace the line that looks like this:
COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }}
with this line:
COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}
2. Configuration options
2.1. Packages in subdirectories
By default, CompatHelper expects your git repository to contain a single package, and that the Project.toml
for that package exists in the top-level directory. You can indicate that you want CompatHelper to process one or many packages that exist in subdirectories of the git repository by passing the subdirs
keyword to the main function. For example:
CompatHelper.main(; subdirs = ["", "Subdir1", "very/deeply/nested/Subdir2"])
Note that the convention for specifying a top-level directory in the subdirs
keyword is [""]
2.2. Custom registries
To use a list of custom registries instead of the General registry, use the registries
keyword argument. For example:
my_registries = [Pkg.RegistrySpec(name = "General",
uuid = "23338594-aafe-5451-b93e-139f81909106",
url = "https://github.com/JuliaRegistries/General.git"),
Pkg.RegistrySpec(name = "BioJuliaRegistry",
uuid = "ccbd2cc2-2954-11e9-1ccf-f3e7900901ca",
url = "https://github.com/BioJulia/BioJuliaRegistry.git")]
CompatHelper.main(; registries = my_registries)
2.3. Custom pre-commit hooks
CompatHelper supports running a custom function (called a "precommit hook") just before commiting changes. To provide a precommit hook, simple pass a zero-argument function as the first argument to CompatHelper.main
.
2.3.1. Default precommit hook
If you do not specify a precommit hook, CompatHelper will run the default precommit hook (CompatHelper.update_manifests
), which updates all Manifest.toml
files in your repository.
2.3.2. Examples
Example 1: Disable all precommit hooks
If you want to disable all precommit hooks, simply pass a dummy function that does nothing:
run: julia -e '
using CompatHelper;
CompatHelper.main( () -> () );'
Example 2: Print a logging message
You can add functionality by passing your own zero-argument function to CompatHelper.main
, like so:
run: julia -e '
using CompatHelper;
CompatHelper.main() do;
CompatHelper.update_manifests();
println("I did it!");
end;'
This snippet uses ;
to specify the ends of lines, because according to YAML, the entire block of Julia code is a single line.
Also to note is that you cannot use '
inside of your Julia command, since it's used to quote the Julia code.
A full example is available here.
Manifest.toml
in the root of the repository
Example 3: Only update the The following snippet tells CompatHelper to update the Manifest.toml
file in the root of the repository but not any of the other Manifest.toml
files. So, for example, /Manifest.toml
will be updated, but /docs/Manifest.toml
, /examples/Manifest.toml
, and /test/Manifest.toml
will not be updated.
run: julia -e 'using CompatHelper; CompatHelper.main( (; registries) -> CompatHelper._update_manifests(String[pwd()]; registries = registries, delete_old_manifest = true) )'
If the keyword argument delete_old_manifest
is set to true, as in the above example, then CompatHelper
updates the Manifest.toml file by deleting the Manifest and running Pkg.update()
in order to generate a new
one. If delete_old_manifest=false
, then CompatHelper runs Pkg.update()
without first deleting the Manifest.
2.4. Overriding the default branch
By default, CompatHelper will open pull requests against your repository's default branch. If you would like to override this behavior, set the master_branch
keyword argument. For example:
CompatHelper.main(; master_branch = "my-custom-branch")
3. Troubleshooting
If CompatHelper is failing despite everything being setup correctly following the previous instructions, try to delete the Manifest.toml
file from the src
folder (and from the test
folder if any). See this issue for more details.
4. Self hosting and other environments
It's possible to run CompatHelper on your infrastructure in case of GitHub Enterprise or other setups.
Basically it should be all configurable by passing values to CompatHelper.main()
function.
To run it on GitHub Enterprise, e.g. on address github.company.com
you can do
using CompatHelper
ENV["GITHUB_TOKEN"] = "github access token"
ENV["GITHUB_REPOSITORY"] = "org/repo"
username = "github user name that matches the access token"
email = "email address"
CompatHelper.main(CompatHelper.update_manifests,
ENV,
CompatHelper.GitHubActions(username, email);
hostname_for_api = "https://github.company.com/api/v3",
hostname_for_clone = "github.company.com")
To run it on TeamCity instead of GitHub Actions, you need to specify the ci_cfg
parameter, e.g. like this.
using CompatHelper
CompatHelper.main(CompatHelper.update_manifests,
ENV,
CompatHelper.TeamCity(<your bot github account username>, <your bot github email>)
)
Because of high configurability of TeamCity it's advised to pass the TeamCity structure explicitly without usage of the
auto_detect_ci_service
function, which is suitable for some simpler setups.
5. Acknowledgements
CompatHelper was originally created by the Brown Center for Biomedical Informatics at Brown University.
This work was supported in part by National Institutes of Health grants U54GM115677, R01LM011963, and R25MH116440. The content is solely the responsibility of the authors and does not necessarily represent the official views of the National Institutes of Health.