This repo has three independent release streams:
- Crate release stream:
- Version source:
Cargo.toml([package].version) - Changelog:
CHANGELOG.md - Tags:
vX.Y.Z - Automation:
.github/workflows/release.yml(publishes crate, binaries, release notes)
- Version source:
- Schema artifact release stream:
- Version source:
SCHEMA_VERSION - Schema file:
schemas/envgen.schema.vA.B.C.json - Changelog:
SCHEMA_CHANGELOG.md - Tags:
schema-vA.B.C - Automation: no publish workflow is triggered by schema tags
- Version source:
- Homebrew tap sync stream:
- Source tag: crate tag
vX.Y.Zfromsmorinlabs/envgen - Formula host repo:
smorinlabs/homebrew-tap - Formula path:
Formula/envgen.rb - Automation:
.github/workflows/homebrew-tap-pr.yml(opens/updates PR in tap repo)
- Source tag: crate tag
smorinlabs/envgenowns:- release tag (
vX.Y.Z) creation - source tarball URL + SHA256 resolution
- automation code (
scripts/homebrew/tap_release.py,make homebrew-*) - workflow that opens/updates tap PRs (
.github/workflows/homebrew-tap-pr.yml)
- release tag (
smorinlabs/homebrew-tapowns:- formula files (
Formula/*.rb) - PR review/merge policy for tap updates
- optional tap-native CI
- formula files (
Homebrew/homebrew-coreis future/optional:- no required release gate for
envgen - existing
release.ymlhomebrew-corejob remains non-blocking until formula exists upstream
- no required release gate for
For release tag vX.Y.Z, the formula source URL is:
https://github.com/smorinlabs/envgen/archive/refs/tags/vX.Y.Z.tar.gz
Behavior:
- GitHub serves this as a redirect (
302) to codeload, then200when the tag exists. - This archive is generated from the git tag; it is not uploaded by release assets.
- Formula
sha256must be computed from this tarball content.
Current verified example:
v1.0.0(published2026-02-16T20:11:01Z) resolves successfully via the URL above.
Configure the crate in crates.io to trust this repository and workflow:
- Open crate settings on crates.io for
envgen. - Add a Trusted Publisher for GitHub Actions.
- Set owner/repo to
smorinlabs/envgen. - Set workflow file to
.github/workflows/release.yml. - Set environment to
crates-io.
This mapping must match the publish job in .github/workflows/release.yml exactly.
- Rust is patch-pinned at
1.88.0viarust-toolchain.toml. Cargo.tomlrust-versionis also1.88.0.- CI/release workflows set Rust
1.88.0explicitly to keep local and automation behavior aligned.
make version-statusmake check-coremake check-msrvmake check-securitymake check-releasemake sync-lockfilemake check-lockfilemake precommit-fastmake prepush-fullmake bump-crate LEVEL=patch|minor|majormake bump-crate VERSION=X.Y.Zmake bump-crate-patch|bump-crate-minor|bump-crate-majormake bump-schema LEVEL=patch|minor|majormake bump-schema VERSION=A.B.Cmake bump-schema-patch|bump-schema-minor|bump-schema-majormake bump-dry-run MODE=crate|schema LEVEL=...make bump-dry-run MODE=crate|schema VERSION=...make tag-cratemake push-tag-cratemake tag-schemamake push-tag-schemamake homebrew-status TAG=vX.Y.Zmake homebrew-source TAG=vX.Y.Zmake homebrew-sync-formula TAG=vX.Y.Z TAP_REPO_DIR=/path/to/homebrew-tapmake homebrew-verify-formula TAG=vX.Y.Z TAP_REPO_DIR=/path/to/homebrew-tapmake homebrew-open-tap-pr TAG=vX.Y.Z TAP_REPO_DIR=/path/to/homebrew-tapmake homebrew-release-tap TAG=vX.Y.Z TAP_REPO_DIR=/path/to/homebrew-tap
Release-flow commands print a Hint: + Next: block to guide the next command in the sequence.
- Default behavior:
- Hints are shown for local interactive runs (TTY).
- Hints are suppressed in CI/non-interactive output.
- Override behavior:
ENVGEN_HINTS=1forces hints on.ENVGEN_HINTS=0forces hints off.
Commands with guided next-step output include:
make bump-crate*make check-releasemake tag-cratemake push-tag-cratemake bump-schema*make check-schemamake tag-schemamake push-tag-schemamake homebrew-sourcemake homebrew-sync-formulamake homebrew-verify-formulamake homebrew-open-tap-pr
Example (crate flow):
$ make bump-crate-patch
...
Hint: Crate release prep updated to vX.Y.Z.
Next:
$ make check-release
$ make check-release
...
✓ Release readiness checks passed for crate vX.Y.Z
Hint: Release readiness checks passed for crate vX.Y.Z.
Next:
$ git add Cargo.toml Cargo.lock CHANGELOG.md
$ git commit -m "chore(release): bump crate to vX.Y.Z"
$ git push origin main
$ make tag-crate
Example (schema flow):
$ make bump-schema-patch
...
Hint: Schema release prep updated to vA.B.C.
Next:
$ make check-schema
$ make check-schema
...
Hint: Schema checks passed for artifact vA.B.C.
Next:
$ git add SCHEMA_VERSION SCHEMA_CHANGELOG.md schemas/envgen.schema.vA.B.C.json
$ git commit -m "chore(schema): schema-vA.B.C"
$ git push origin main
$ make tag-schema
| Entry point | Canonical target | Purpose |
|---|---|---|
| Local commit hook | make precommit-fast |
Fast non-mutating checks before commit |
| Local pre-push hook | make prepush-full |
Full quality/security/MSRV checks before push |
| Local/manual core parity | make check-core |
Core checks shared by CI Linux and release Linux verification |
| CI Linux | make check-core |
Core release-parity verification |
| CI macOS | make check-rust |
Rust-only portability checks |
| CI MSRV | make check-msrv |
Declared MSRV correctness |
| CI security | make check-security |
Audit/dependency/spelling checks |
| Release verification (Linux) | make check-core |
Same core gate as CI Linux |
| Release verification (macOS) | make check-rust |
Rust-only portability checks |
| Local release readiness | make check-release |
check-core + cargo publish --dry-run --locked --allow-dirty |
- Install git hooks once:
make pre-commit-setup
- Run fast checks when iterating:
make precommit-fast
- Run full checks before pushing:
make prepush-full
- Before tagging a crate release:
make check-release
Tag commands are file-first by default:
make tag-crate/make push-tag-crateread version fromCargo.toml.VERSION=X.Y.Zis the only override.
make tag-schema/make push-tag-schemaread version fromSCHEMA_VERSION.SCHEMA_VERSION=A.B.Cis the only override.
Overrides must match the corresponding file value; mismatches fail fast.
| Command | Updates | Does not update | Tag behavior |
|---|---|---|---|
make bump-crate ... |
Cargo.toml, CHANGELOG.md |
SCHEMA_VERSION, schemas/envgen.schema.v*.json, SCHEMA_CHANGELOG.md |
Does not create or push tags |
make bump-schema ... |
SCHEMA_VERSION, schemas/envgen.schema.v*.json, SCHEMA_CHANGELOG.md |
Cargo.toml, CHANGELOG.md |
Does not create or push tags |
make tag-crate / make push-tag-crate |
Local crate tag and optional remote push | Schema version files/changelog | Uses Cargo.toml version by default; VERSION=... override must match file value; tag is vX.Y.Z |
make tag-schema / make push-tag-schema |
Local schema tag and optional remote push | Crate version files/changelog | Uses SCHEMA_VERSION file value by default; SCHEMA_VERSION=... override must match file value; tag is schema-vA.B.C |
make bump-*commands only edit files and never create/push tags.make tag-*commands create local annotated tags only.make push-tag-*commands only push existing local tags.
This is intentional to prevent accidental release workflow triggers.
Run a dry-run before applying changes:
make bump-dry-run MODE=crate LEVEL=patch
make bump-dry-run MODE=schema LEVEL=patchYou can also provide explicit versions:
make bump-dry-run MODE=crate VERSION=X.Y.Z
make bump-dry-run MODE=schema VERSION=A.B.C- Make sure
mainis green (CI passing). - Preview the crate bump:
make bump-dry-run MODE=crate LEVEL=patch
- Apply the crate bump:
make bump-crate LEVEL=patch(orVERSION=X.Y.Z)- This updates
Cargo.toml,CHANGELOG.md, and synchronizesCargo.lock.
- Validate:
make check-release
- Commit release prep (recommended):
chore(release): vX.Y.Z
- Create local tag:
make tag-crate
- Push tag:
make push-tag-crate
- Watch GitHub Actions
Releaseworkflow.
The release workflow at .github/workflows/release.yml runs when:
- You push a tag matching
v*.*.*, or - You manually run the workflow (
workflow_dispatch) and provide an existing tag.
- Update schema content as needed in
schemas/envgen.schema.v<current>.json. - Preview the schema artifact bump:
make bump-dry-run MODE=schema LEVEL=patch
- Apply schema artifact bump:
make bump-schema LEVEL=patch(orVERSION=A.B.C)
- Validate:
make check-schema
- Commit schema release prep (recommended):
chore(schema): schema-vA.B.C
- Create local schema tag:
make tag-schema
- Push schema tag:
make push-tag-schema
Pushing schema-v*.*.* tags does not trigger crates.io publish.
- Ensure a crate release tag exists in
smorinlabs/envgen:- e.g.
v1.0.0
- e.g.
- Prepare source metadata:
make homebrew-source TAG=v1.0.0
- Sync formula in tap clone:
make homebrew-sync-formula TAG=v1.0.0 TAP_REPO_DIR=/Users/stevemorin/c/homebrew-tap
- Verify formula:
make homebrew-verify-formula TAG=v1.0.0 TAP_REPO_DIR=/Users/stevemorin/c/homebrew-tap
- Open/update tap PR:
make homebrew-open-tap-pr TAG=v1.0.0 TAP_REPO_DIR=/Users/stevemorin/c/homebrew-tap
Automation equivalent:
- Tag push triggers
.github/workflows/release.yml. release.ymljobdispatch-homebrew-tap-prexplicitly dispatches.github/workflows/homebrew-tap-pr.ymlusingworkflow_dispatchwithtag=vX.Y.Z.- You can manually retry the tap workflow with:
gh workflow run homebrew-tap-pr.yml -R smorinlabs/envgen -f tag=vX.Y.Z
Use a fine-grained PAT for this (this is HOMEBREW_TAP_GITHUB_TOKEN, not HOMEBREW_GITHUB_API_TOKEN).
- Go to GitHub: Profile photo ->
Settings->Developer settings->Personal access tokens->Fine-grained tokens->Generate new token. - Set:
Resource owner:smorinlabsRepository access:Only select repositories- Select repo:
smorinlabs/homebrew-tap
- Under Repository permissions, set:
Contents:Read and writePull requests:Read and write
- Set expiration (recommended: short, e.g. 90 days), then click
Generate token. - Copy the token immediately (you won’t be able to view it again).
- If GitHub shows token status
pending(org approval enabled), approve it in org token settings. - Add it to
smorinlabs/envgensecrets:- Repo ->
Settings->Secrets and variables->Actions->New repository secret - Name:
HOMEBREW_TAP_GITHUB_TOKEN - Value: token from step 5
- Repo ->
- Test it:
gh workflow run homebrew-tap-pr.yml -R smorinlabs/envgen -f tag=v1.0.1
CLI shortcut for step 7:
printf %s "$TOKEN" | gh secret set HOMEBREW_TAP_GITHUB_TOKEN -R smorinlabs/envgenDocs:
- Missing release section for tagging:
make tag-cratefails unlessCHANGELOG.mdcontains## [X.Y.Z] - YYYY-MM-DD.make tag-schemafails unlessSCHEMA_CHANGELOG.mdcontains## [A.B.C] - YYYY-MM-DD.
- Override mismatch:
VERSION=... make tag-cratefails if override does not matchCargo.toml.SCHEMA_VERSION=... make tag-schemafails if override does not matchSCHEMA_VERSION.
- Missing local tag on push:
make push-tag-cratefails ifvX.Y.Zhas not been created locally.make push-tag-schemafails ifschema-vA.B.Chas not been created locally.
- Empty
Unreleasedsection during bump:- Crate override:
make bump-crate-patch ALLOW_EMPTY_CHANGELOG=1 - Schema override:
make bump-schema-patch ALLOW_EMPTY_SCHEMA_CHANGELOG=1
- Crate override:
- Lockfile mismatch during locked checks:
- Symptom:
Cargo.lock needs to be updated but --locked was passed - Fix:
make sync-lockfile
- Symptom:
- Partial update on bump failure:
- A failed bump can leave version/changelog edits before later steps complete.
- Recovery: run
make sync-lockfileand retry the bump after fixing the reported error.
- Homebrew tap workflow dispatch failure:
- Symptom:
release.ymljobDispatch Homebrew Tap PR workflowfails. - Impact: crate release remains successful (non-blocking), but tap sync does not start automatically.
- Fix: check the dispatch job logs and repo workflow permissions (
actions: write), then run:gh workflow run homebrew-tap-pr.yml -R smorinlabs/envgen -f tag=vX.Y.Z
- Symptom:
- Homebrew tap token auth/permission errors:
- Symptom: workflow step
Validate tap token permissionsfails with::error::output. - Fix: follow
Reset HOMEBREW_TAP_GITHUB_TOKEN (step-by-step)in this document.
- Symptom: workflow step
For migration safety, token-based publish remains available through
.github/workflows/publish-fallback.yml (manual trigger only).
- This workflow requires the
CARGO_REGISTRY_TOKENsecret in thecrates-ioenvironment. - Keep fallback enabled for exactly 2 successful releases after Trusted Publishing goes live.
- After 2 successful releases:
- Remove
.github/workflows/publish-fallback.yml. - Remove
CARGO_REGISTRY_TOKENfrom GitHub secrets.
- Remove
- This setup assumes you use "Squash and merge" and "Default to PR title for squash merge commits" in GitHub settings so your main-branch commits stay Conventional.
- Tap PR automation requires
HOMEBREW_TAP_GITHUB_TOKENsecret with write access tosmorinlabs/homebrew-tap. - homebrew-core bump PRs require the
HOMEBREW_GITHUB_API_TOKENsecret (a GitHub token able to open PRs againstHomebrew/homebrew-core). - The homebrew-core automation will no-op until the
envgenformula exists inHomebrew/homebrew-core.