# Releases A release binds a Git tag to a title, Markdown notes and named assets. There is one release per tag. Published releases follow repository visibility; drafts are visible only to writers. The web Releases tab is read-only. ```sh ermite release create app v1.0.0 --target main --title 'Version 1' --notes-file notes.md --asset dist/app ermite release list app --json ermite release view app latest ermite release edit app v1.0.0 --notes 'Updated notes' ermite release upload app v1.0.0 dist/app --clobber ermite release download app latest --pattern 'app*' --dir downloads ermite release delete app v1.0.0 --yes ``` Create/edit accept `--draft`, `--prerelease`, `--latest`, `--target` and notes. Use `edit --publish` to publish a draft, `--no-prerelease` to clear that flag. An existing tag never moves; `--target` creates a missing tag. A draft can name a missing tag. Deleting a tag turns its release into a draft and keeps its assets; recreating the tag does not republish it. Deleting a release does not delete the tag. `latest` is the newest published non-prerelease by creation time and id, unless pinned with `--latest` / REST `make_latest: "true"`. Drafting or deleting the pinned release clears the pin. Asset names are unique within a release, 1–255 characters, without slashes, backslashes or control characters. CLI `--clobber` replaces a same-named asset; REST publishers delete it then upload again. Writes require `release:write` (included in the `cli` preset), or a CI job token with `permissions: contents: write` for that repository. Branch-limited tokens cannot write releases. Read access to a private repository needs `repo:read`; unreadable releases, including drafts, answer not found. Older servers without the `releases` feature are refused by the CLI. ## Limits and storage | Variable | Default | |---|---| | `ERMITE_RELEASE_ASSET_MAX` | `2GiB` per asset | | `ERMITE_RELEASE_ASSETS_MAX` | `1000` per release | | `ERMITE_RELEASE_QUOTA` | `20GiB` per repository | Quota includes uploads in progress. Exceeding limits gives REST 422 or RPC `resource_exhausted`. Assets use the shared [blob store](storage.md), disk by default or S3. Downloads pass through ermite, never redirect to the bucket, and support single byte ranges with 206, Content-Length and Content-Disposition. Stable links: - `//releases/download//` - `//releases/latest/download/` ## GitHub-compatible publishers REST is at `/-/github/api`, uploads at `/-/github/api/uploads`. Use the external `ERMITE_PUBLIC_URL`, not the S3 endpoint. Stored-token publishers need `release:write` and, for private repository reads, `repo:read`. The owner component is `ERMITE_OWNER` (`owner` by default). GoReleaser configuration (replace the host and repository): ```yaml version: 2 github_urls: api: https://git.example.org/-/github/api/ upload: https://git.example.org/-/github/api/uploads/ download: https://git.example.org/ release: github: owner: owner name: app ``` Run `GITHUB_TOKEN= goreleaser release --clean` from a tagged checkout. On an ermite runner, the job supplies `GITHUB_API_URL`, `GITHUB_SERVER_URL` and `GITHUB_TOKEN`; no endpoint override is needed for action-gh-release: ```yaml name: release on: push: tags: ['v*'] permissions: contents: write jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: mkdir -p dist && printf 'hello\n' > dist/app.txt - uses: softprops/action-gh-release@v2 with: files: dist/* body: Release built by CI ``` `contents: read` is insufficient and gets 403. Automatic release-note generation, discussions, reactions, immutability and attestations are not supported.