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.
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, 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:
/<repo>/releases/download/<tag>/<asset>
/<repo>/releases/latest/download/<asset>
GitHub-compatible publishers
REST is at <public URL>/-/github/api, uploads at
<public URL>/-/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):
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=<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:
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.
source
1# Releases
2
3A release binds a Git tag to a title, Markdown notes and named assets. There is
4one release per tag. Published releases follow repository visibility; drafts
5are visible only to writers. The web Releases tab is read-only.
6
7```sh
8ermite release create app v1.0.0 --target main --title 'Version 1' --notes-file notes.md --asset dist/app
9ermite release list app --json
10ermite release view app latest
11ermite release edit app v1.0.0 --notes 'Updated notes'
12ermite release upload app v1.0.0 dist/app --clobber
13ermite release download app latest --pattern 'app*' --dir downloads
14ermite release delete app v1.0.0 --yes
15```
16
17Create/edit accept `--draft`, `--prerelease`, `--latest`, `--target` and notes.
18Use `edit --publish` to publish a draft, `--no-prerelease` to clear that flag.
19An existing tag never moves; `--target` creates a missing tag. A draft can name a
20missing tag. Deleting a tag turns its release into a draft and keeps its assets;
21recreating the tag does not republish it. Deleting a release does not delete the tag.
22
23`latest` is the newest published non-prerelease by creation time and id, unless
24pinned with `--latest` / REST `make_latest: "true"`. Drafting or deleting the
25pinned release clears the pin. Asset names are unique within a release, 1–255
26characters, without slashes, backslashes or control characters. CLI `--clobber`
27replaces a same-named asset; REST publishers delete it then upload again.
28
29Writes require `release:write` (included in the `cli` preset), or a CI job token
30with `permissions: contents: write` for that repository. Branch-limited tokens
31cannot write releases. Read access to a private repository needs `repo:read`;
32unreadable releases, including drafts, answer not found. Older servers without
33the `releases` feature are refused by the CLI.
34
35## Limits and storage
36
37| Variable | Default |
38|---|---|
39| `ERMITE_RELEASE_ASSET_MAX` | `2GiB` per asset |
40| `ERMITE_RELEASE_ASSETS_MAX` | `1000` per release |
41| `ERMITE_RELEASE_QUOTA` | `20GiB` per repository |
42
43Quota includes uploads in progress. Exceeding limits gives REST 422 or RPC
44`resource_exhausted`. Assets use the shared [blob store](storage.md), disk by
45default or S3. Downloads pass through ermite, never redirect to the bucket, and
46support single byte ranges with 206, Content-Length and Content-Disposition.
47Stable links:
48
49- `/<repo>/releases/download/<tag>/<asset>`
50- `/<repo>/releases/latest/download/<asset>`
51
52## GitHub-compatible publishers
53
54REST is at `<public URL>/-/github/api`, uploads at
55`<public URL>/-/github/api/uploads`. Use the external `ERMITE_PUBLIC_URL`, not
56the S3 endpoint. Stored-token publishers need `release:write` and, for private
57repository reads, `repo:read`. The owner component is `ERMITE_OWNER` (`owner` by
58default).
59
60GoReleaser configuration (replace the host and repository):
61
62```yaml
63version: 2
64github_urls:
65 api: https://git.example.org/-/github/api/
66 upload: https://git.example.org/-/github/api/uploads/
67 download: https://git.example.org/
68release:
69 github:
70 owner: owner
71 name: app
72```
73
74Run `GITHUB_TOKEN=<token> goreleaser release --clean` from a tagged checkout.
75
76On an ermite runner, the job supplies `GITHUB_API_URL`, `GITHUB_SERVER_URL` and
77`GITHUB_TOKEN`; no endpoint override is needed for action-gh-release:
78
79```yaml
80name: release
81on:
82 push:
83 tags: ['v*']
84permissions:
85 contents: write
86jobs:
87 publish:
88 runs-on: ubuntu-latest
89 steps:
90 - uses: actions/checkout@v4
91 - run: mkdir -p dist && printf 'hello\n' > dist/app.txt
92 - uses: softprops/action-gh-release@v2
93 with:
94 files: dist/*
95 body: Release built by CI
96```
97
98`contents: read` is insufficient and gets 403. Automatic release-note generation,
99discussions, reactions, immutability and attestations are not supported.