ergon sets up a repository with a managed baseline. It also keeps the license header of every file, and releases the packages of the repository. It works on repositories in one or more of eleven languages: C#, Java, Kotlin, PHP, JavaScript, TypeScript, Go, Python, Rust, Terraform and Bash.
| Command | What it does |
|---|---|
ergon init |
Renders the baseline: the GitHub workflows, the Makefile, the hooks of pre-commit, one linter configuration per language, and the license files |
ergon license |
Adds and checks the license header of every file |
ergon release |
Plans the releases from changeset files, writes the versions and the changelogs in a version pull request, and publishes the packages when the pull request merges |
ergon tool run |
Installs and runs the tools of .ergon.yaml at their pinned versions |
ergon tool path |
Installs a tool of .ergon.yaml and prints its program, such as zig as the C compiler of a build |
Each release has archives for Linux, macOS and Windows on amd64 and arm64, deb, rpm and apk packages for Linux, and checksums.txt with the SHA-256 digest of each file. cosign signs checksums.txt without a key, and each archive and package has an SPDX SBOM. Download the archive for your system, check its digest, and put ergon on your PATH. gh attestation verify <file> --repo dokimasia/ergon checks the build provenance of an archive, a package or the installed binary of a release, such as gh attestation verify "$(command -v ergon)" --repo dokimasia/ergon.
With Homebrew, install the cask of the tap:
brew install --cask dokimasia/tap/ergonWith Go 1.27.3 or later, install the command from source:
go install go.dokimi.dev/ergon/cmd/ergon@latestergon --version prints the version of the release.
Set up a repository with Go:
ergon init new --language go --owner "Example B.V." --license MIT \
--repository example/demo --security-contact security@example.com
make help
make checkergon init new writes the managed files, the seeded files such as README.md, .ergon.yaml and .ergon/init.lock. Commit the lock with the files. Then:
- Add a language with
ergon init add typescript. - Change an option in
.ergon.yaml, such as the version of a tool, and runergon init sync. - Run
ergon init checkto list the managed files that differ from the baseline. - Run
ergon init upgradeto move to the baseline of the newest release of ergon.
ergon init sorts each file of the baseline into a class:
| Class | Examples | Who changes it |
|---|---|---|
| Managed | Makefile, .github/workflows/ci.yml, .golangci.yml |
ergon init renders it. Write a setting of the repository to the same path under .ergon/local, and ergon init merges it in |
| Seeded | README.md |
ergon init writes it when it is absent, and the repository maintains it |
| Options | .ergon.yaml |
The repository changes an option, and ergon init renders the managed files from it |
| Lock | .ergon/init.lock |
ergon init records its answers, the baseline value of each option and the digest of each managed file |
The Makefile has the same targets in every repository:
| Target | Runs |
|---|---|
make fmt |
The formatters of every language |
make lint |
The linters of every language |
make test |
The tests of every language |
make generate |
The generators of every language |
make audit |
The vulnerability scan of every language |
make check |
The gate of every language, as CI runs it |
make help |
The targets in groups: the common targets, each language, and the targets of the repository |
Each language adds its own targets, such as lint-go and check-go. The hooks of pre-commit run make lint and make test before each commit, and make check before each push. The option common.hooks of .ergon.yaml changes the targets of each stage.
ergon release follows the workflow of changesets:
- A pull request adds a changeset with
ergon release add. The changeset lists each package that the change releases, with its bump. - When the CI run of a push to
mainpasses,version.ymlopens or updates the version pull request. It writes the new versions, the requirements between the packages and the changelogs. - The merge of the version pull request publishes the packages.
release.ymlchecks that a CI run passed on the content of the commit, and then packs, tags and publishes each package.
ergon release status reports each package that a branch changed without a changeset. A run of ci.yml skips its jobs when a passed run already covers its content, such as the run of a version pull request whose parent passed. A repository can set the variable ERGON_APP_CLIENT_ID and the secret ERGON_APP_PRIVATE_KEY of a GitHub App, so that the checks of the version pull request start without an approval.
ergon release publishes these packages:
- Go modules, through their tags
- the projects of a uv workspace, to PyPI
- the packages of an npm or a pnpm workspace, to the npm registry
- the crates of a Cargo workspace, to crates.io
The job publish of release.yml uploads through trusted publishing. Each project on pypi.org, each package on npmjs.com and each crate on crates.io needs a trusted publisher for the repository, the workflow release.yml and the environment release. npm and crates.io configure a trusted publisher only for a package that they already have, so publish the first version of a package by hand. Then rerun the failed job publish of that release. It skips the upload of a version that the registry has, and writes the tag and the release of the version. A trusted publisher of npm also has to allow npm publish. Cargo packages and publishes crates that require each other in one run from version 1.90, so such a workspace pins Cargo 1.90 or later in rust-toolchain.toml. The roadmap lists the releases of the other toolchains.
A command of go.binaries in .ergon.yaml with registry: terraform is a provider of the Terraform Registry. Its release remains a draft after the publish. The draft has the zips of the provider, its manifest and the checksums <name>_<version>_SHA256SUMS, which cosign signs in the job pack. The Terraform Registry requires a GPG signature of the checksums, so you complete the draft on a workstation with your key:
GITHUB_REPOSITORY=example/terraform-provider-demo GITHUB_TOKEN="$(gh auth token)" \
ergon release sign --key 0123456789ABCDEF0123456789ABCDEF01234567ergon release sign checks the cosign bundle of the checksums against the release workflow at the commit of the tag. It also checks the digest of each asset of the draft against the checksums. It then signs the checksums with gpg, uploads the signature and publishes the release, and the webhook of the Terraform Registry ingests the version. The Terraform Registry accepts a key of the type RSA or DSA.
| Directory | Contents |
|---|---|
| docs/architecture | The modules and the packages, and what each may import |
| docs/rfc | The designs and the argument behind them |
| docs/adr | The decisions and what they cost |
| docs/roadmap | The order of the work |
The targets of the Makefile and the hooks of .pre-commit-config.yaml run ergon from the checkout with go run go.dokimi.dev/ergon/cmd/ergon. They do not need an installed ergon:
pre-commit install
make checkmake check runs the gate of the repository: the linters, the tests, the tests under the race detector and the vulnerability scan of every module. CONTRIBUTING.md describes how to propose a change, and SECURITY.md how to report a vulnerability.
ergon is licensed under the MIT license, copyright Dokimasia B.V. See LICENSE.