Skip to main content

GitHub Releases

Create GitHub releases with uploaded assets

The release stage creates a GitHub release and uploads all artifacts as assets.

Classification

GroupRequired (default)RollbackToken scope
Assetstruedelete release + delete tag + delete assetscontents:write

See Release resilience for the full classification table and the Submitter gate semantics.

The required: field

Default: true — a GitHub Releases failure fails the release.

Set required: false to log failures but continue:

crates:
  - name: myapp
    release:
      required: false   # continue release even if GitHub Release upload fails
      github:
        owner: myorg
        name: myapp

See Publish overview — the required: field for the full semantics.

Minimal config

crates:
  - name: myapp
    release:
      github:
        owner: myorg
        name: myapp

If github.owner and github.name are omitted, anodizer auto-detects them from the git remote URL.

Release config fields

FieldTypeDefaultDescription
github.ownerstringauto-detectedGitHub owner/org
github.namestringauto-detectedRepository name
draftboolfalseCreate as draft release
prereleasestring/boolautoMark as prerelease: auto (detect from version), true, false
make_lateststring/boolautoMark as latest: auto, true, false
name_templatestring{{ Tag }}Release title
headerstringnoneText prepended to release body
footerstringnoneText appended to release body
extra_fileslistnoneAdditional files to upload (glob patterns)
skip_uploadboolfalseCreate release without uploading assets
replace_existing_draftboolfalseReplace existing draft release. See Recovery flags.
replace_existing_artifactsboolfalseOverwrite existing assets. See Recovery flags.
on_failurestringrollbackIn-process failure policy: rollback or hold. See Release resilience.

Full config reference

release:
  github:
    owner: myorg              # auto-detected from git remote if omitted
    name: myapp
  draft: false
  prerelease: auto            # auto | true | false
  make_latest: auto           # auto | true | false
  name_template: "{{ Tag }}"
  header: ""                  # text prepended to release body
  footer: ""                  # text appended to release body
  extra_files: []             # glob patterns for additional uploads
  skip_upload: false          # bool or template string
  replace_existing_draft: false
  replace_existing_artifacts: false
  mode: ""                    # keep-existing | append | prepend | replace
  ids: []
  exclude: []                 # drop assets whose name matches a glob
  skip: false
  on_failure: rollback        # rollback | hold (auto-degrades to hold past one-way doors)

Excluding sidecars with exclude

exclude is a list of globs matched against each release asset's file name; anodizer drops every asset whose name matches at least one glob before attaching it to this GitHub release only (a mirror configured elsewhere is unaffected). Use it to keep heavy sidecars (checksums, signatures, SBOMs) off the GitHub release while archives still attach.

release:
  github: { owner: my-org, name: my-repo }
  exclude:
    - "*.sha256"
    - "*.sig"
    - "*.cdx.json"

exclude composes with ids: — an asset attaches only when it passes both filters. An empty or unset exclude keeps everything. Globs are validated at config-load; an exclude that drops every candidate raises a warning so a typo'd glob is never a silent empty release. The verify-release gate applies the same exclude, so a deliberately-excluded signature or SBOM is not flagged as a missing asset.

Authentication

Set GITHUB_TOKEN as an environment variable or pass it via --token:

export GITHUB_TOKEN="ghp_..."
anodizer release

Common gotchas

  • Draft vs published: a draft release is only visible to repo collaborators. Set draft: false (the default) for publicly visible releases.
  • make_latest: auto: by default, anodizer marks a release as latest only when the version is not a prerelease. Override with make_latest: true or make_latest: false.
  • Asset name collisions: if two artifacts have the same filename, the second upload returns a 422. Set replace_existing_artifacts: true on the release: block to overwrite.

Republish / update behavior

Use replace_existing_draft: true and replace_existing_artifacts: true on the release: block for re-runnable workflows. See Recovery flags for the full mechanism.

Draft releases

release:
  draft: true

Prerelease detection

When prerelease: auto (default), anodizer detects prereleases from the version string. Versions like 1.0.0-rc.1, 1.0.0-beta.2 are automatically marked as prereleases.

Extra files

Upload additional files that aren't part of the pipeline:

release:
  extra_files:
    - "dist/completions/*"
    - "docs/man/*.1"

Full example

crates:
  - name: myapp
    release:
      github:
        owner: myorg
        name: myapp
      name_template: "{{ ProjectName }} {{ Version }}"
      header: |
        ## What's Changed
      footer: |
        **Full Changelog**: https://github.com/myorg/myapp/compare/{{ PreviousTag }}...{{ Tag }}
      prerelease: auto
      make_latest: auto