A full-process release workflow for software projects. Applicable to any type of project on GitHub.
Applicable Scenarios
The complete release cycle of a GitHub project: from version number determination to CI build verification. CI troubleshooting (references/ci-troubleshooting.md) and project-type-specific guides (the various documents underreferences/ ) serve as supplementary references for the release process.
Boundary of responsibilities with git-workflow: This skill is only responsible for CI build monitoring within the release process (Step 4) and release cost constraints (quota red light). Daily Actions quota governance—CI minutes exhaustion stopgap, workflow suspension/resumption, workflow_dispatch conversion, repository-level master switch—is handled by git-workflow §11. When CI failures occur during release: for build artifact/signing/release pipeline issues, read this skill; for account-level quota governance issues, refer to git-workflow.
Project Configuration
config/projects.yaml Centrally manages the release configuration of each project (repository, platform, auto-update, excluded artifacts, etc.). When releasing, first read the corresponding project configuration, and determine the build matrix and expected artifacts according to the configuration. For a template, see config/projects.example.yaml。
For desktop projects with in-app updates, you must also read Real Upgrade and Hotfix Gates: signature verification, old client capabilities, process reclamation, data recovery, and actual installation paths are each verified separately.
Pre-release Checks
| Check Item | Description |
|---|---|
| Clean workspace | git status No uncommitted changes |
| Consistent version numbers | All version number files (package.json / Cargo.toml / pyproject.toml, etc.) are consistent with the latest entry in CHANGELOG.md |
| CHANGELOG updated | Contains a structured entry for the target version |
| CI workflow exists | .github/workflows/ There is a release-related workflow in and the tag trigger configuration is correct |
| Local test gate | npm test(or the project's corresponding unit test command) passes overall.If a single test fails, rerun first to confirm whether it is intermittentThen classify it: for intermittent flaky failures (regressions not introduced by this change), fix the test or follow up separately, and do not block the release because of it; however, if it reproduces repeatedly across the full suite and points to a real regression, it must be fixed before releasing |
If any condition is not met, fix it first before continuing.
⚠️ Release ≠ Testing — Mandatory Constraint
Tagging / creating a GitHub Release gives the version number to real users, and is not a CI verification mechanism.Treating the release workflow as "checking whether CI passed" or "downloading an artifact to test it myself" is an anti-pattern and must be prohibited.
Why It Is an Absolute Rule
- Actions quota is a limited shared resource. A single cross-platform release (macOS × N + Windows + Linux) usually consumes 300-600 quota minutes, and macOS runners are billed at a 10× rate, contributing the most.
- The hidden cost of mistakenly treating release as testing:
- Once a GitHub Release is created (even as a draft), it is counted in the asset history, polluting the release feed
- After the tag is pushed, people who see the commit may mistakenly think it has been published
- Users may see unstable versions during update checks when auto-update is enabled
- Quota is quickly exhausted, so genuinely urgent hotfixes cannot even run CI
- Being able to do this in the past does not mean it should be done now. GitHub free quota adjustments and macOS runner price increases have both happened, and usage patterns must be updated as costs change.
Prohibited anti-patterns
| Anti-pattern | Symptom | Why it is wrong |
|---|---|---|
| Treating a tag as a smoke test | "I changed one line, let me tag it and see whether CI passes" | One release consumes 300+ quota minutes; 5 tests = one month's quota wiped out |
| Using release to verify build artifacts | "I want to see what the .dmg looks like, so I have to run release" | A dedicated preview / draft build workflow should be used (see below) |
| Publishing multiple patches on the same day / within 24h | v0.3.16 / 17 / 18 released back-to-back within one day, each a successive small fix for the same bug | Save them all for the next release together, instantly saving 60%+ in cost |
| Using draft release as "let me run it once first to try" | "Let me draft release first to see whether the artifact is okay" | A draft runs the full CI just the same, consumes quota just the same, and pollutes release history just the same |
| Single-platform dry-run to verify the build | "Let me run a Linux dry-run first to see, without publishing all platforms" | A dry-run consumes CI time just the same, and once the door is opened it cannot be stopped; switch to a preview workflow |
| Publishing a patch for a small change | "I fixed a typo / changed one line of documentation, so it must be vX.Y.Z" | A pure typo / small documentation change / single-file change does not constitute a reason to release; merge it into the next version with substantive content |
| "The tag is already pushed, and it is already running" | "The v0.3.22 tag has already been pushed, and CI is running anyway" | "It has already been done" is not a reason to keep doing it; record this waste and prevent the next repetition |
Correct approach
A. Want to verify whether CI passes / see what the build artifacts look like?
- Use
pull_request-triggered preview workflow (can run ubuntu only / a single platform, completing in a few tens of minutes) - Or on main use
workflow_dispatchto manually trigger a dry build,withouttriggering the release workflow - Neither of these consumes the high-multiplier macOS quota, and the artifact is visible only to yourself
B. Is there really a fix that users can obtain that needs to be released?
- Wait until 3-5 substantive fixes have accumulated (bug fix / feature / performance / compatibility changes)
- Tag and release once,release only once
- CHANGELOG must have structured entries and cannot be empty
- A regular release must be at least 24 hours after the last tag; a hotfix that blocks installation/update for real users may be released earlier according to the exceptions below (to prevent splitting trial-and-error on the same issue into multiple patches)
Mandatory self-check before tagging (AI must not skip)
Before tagging,the following 5 questions must be answered. When an AI agent is asked to publish a new version, it mustproactivelyprint the final candidate self-check results item by item; if explicit release authorization for that version is missing, ask the user for confirmation, and must not skip verification and tag directly.
- Is this being installed for real users, or is it just an artifact for yourself to look at?
- Does the CHANGELOG already have a structured entry for this version (not empty, not a single-line typo)?
- Is it ≥ 24 hours since the last tag?
- Does this release cumulatively include ≥ 1 substantive fix / feature / change (pure docs / typo / single-line README changes do not count)?
- If any of the above is not satisfied: can this be merged into the next release?
If questions 1, 2, or 4 are answered "no" or the key evidence is unknown: do not tag. If question 3 is under 24 hours, an exception is allowed only for a hotfix that has already reproduced a real installation/update blocker and has explicit user authorization; state the reason, the independent review, and the complete candidate verification results, and do not use exceptions for release trial and error.
AI agent practical rules: Before tagging, explicitly list the answers to the five questions, and bind them to the final candidate and verification. When the user has explicitly authorized this version and the hotfix scope, follow that authorization and do not repeatedly request the same confirmation; when authorization has not been obtained, first complete a reviewable candidate and then confirm. Authorization does not replace verification, and it is forbidden to troubleshoot problems by repeatedly moving the same tag.
Excuse rebuttal table
| Excuse | Reality |
|---|---|
| "I'll just take a quick look, tag it, and roll back immediately" | Pushing the tag has already triggered the full CI, and rolling back the tag cannot refund Actions minutes |
| "The user is pressing for it" | The user does not know your Actions quota; tell them the cost and time of merging it into tomorrow's release and let them choose |
| "Anyway, we've always done it this way" | Being able to do it before does not mean it is reasonable now; this is exactly the direct cause of the 91% quota usage |
| "Only the release workflow runs the full matrix" | Add a preview workflow (costs 10-20% of release); do not make do with release |
| "A draft release does not count as an official release" | Drafts run the full CI just the same, consume quota just the same, and pollute the release history just the same |
| "It's common to ship a patch for small changes" | Pure typos / docs / single-line changes are not a reason to release; merge them into the next version with substantive content |
| "I already tagged it, and it already ran" | "It's already done" is not a reason to keep doing it; record this waste and prevent it from recurring next time |
| "Let's just do a dry-run on a single platform first" | A dry-run consumes CI time just the same, and once you open that door you cannot stop; switch to a preview workflow instead |
| "This time is different; this time it really needs to be released" | SemVer patch versions are inherently allowed to accumulate; isn't releasing next time the better option? |
Red lights (stop when you see any one)
- Wanting to push a second tag within the same workday
- < 24 hours since the last tag
- Wanting to release when the CHANGELOG has no structured entry for this version
- Wanting to use a "draft release" as a test
- Wanting to use
workflow_dispatchto trigger the release workflow as a test (a separate preview workflow should be triggered instead) - This time there are only typos / docs / single-line changes
- macOS 10× quota cumulative usage for the current month is already > 70%
When a red light appears, first stop release side effects and verify the reason. For true hotfix frequency exceptions, see above; retain failure evidence, do not automatically delete or move tags, and publicly released versions must not be overwritten.
🔥 Hotfix and CI retry boundary (critical)
A patch version (X.Y.Z+1) can be Accumulation of new features, or it can be a single hotfix repair. Only by distinguishing them clearly can you avoid the anti-pattern of "treating a release as a test."
When it qualifies as a "hotfix real repair" (publishing a new patch version)
- After the first release, usersactually received a broken build(broken auto-update / failed installation / startup crash)
- The root cause clearly points toa code or configuration bug, with a reproducible failure and a verified fix; if only the CI build fails but no version has yet reached users, do not publish externally on hotfix grounds
- Every new version hasa verifiable commit advancing it(fix one line, change one config, add a test)
Decision signal:gh run view --log-failed The output contains a specific error line (not merely a Timeout / Resource exhausted transient error of this kind).
When it qualifies as "treating a release as a test" (release-by-trial-and-error is prohibited)
- Simply wanting to see whether CI passed or what the artifact looks like
- The last build failed butwithout looking at the failure reasonyou just rebuild directly
- Rebuilding the same version number three or more times (according to the cost curve, more than 3 times is almost always repeated churn over transient issues)
Quick determination of transient vs. real bug
build job 失败:
- 输出含 E0599 / Cargo compile error / 链接错误 → 真实代码 bug,修代码再重打
- 输出含 "Timeout" / "Resource exceeded" / "Killed" → transient,可直接重试
publish job 失败:
- 输出 "Missing signatures" + 产物清单缺 sig → 检查 includeUpdaterJson + bundle.targets(详见 tauri-release.md 红线 8)
- 输出 "Signature not found for the updater JSON. Skipping upload..." → tauri-action 跳过整批 updater,检查 build 产物目录
- 输出 "Unable to download" / "rate limit" → transient
本地单测(vitest / jest)失败,发布前门禁:
- 单条 "Timed out waiting for condition" 超时失败 → 大概率 flaky(轮询式 waitUntil + 动态 import 的异步链在测试环境下偶发跑不完),先重跑该文件确认;连跑仍偶发则修测试(轮询预算给足),不属于本次改动引入的回归,不阻塞发布
- 多条/全量复现、或错误指向具体代码行为 → 真实回归,先修代码再发版
Best practice: first gh release view <tag> --json assets,isDraft,targetCommitish look at the artifact and status, then decide whether to fix the code or rerun a fixed candidate build.
Standard action sequence for fixing a hotfix
- Determine which old version and which stage the reproduction failure occurred in, distinguishing signature verification, preparation, installation, restart, and recovery; read the logs, and do not use a new Release for trial and error.
- Fix in an independent worktree and synchronize the version/CHANGELOG, completing independent review of the fixed candidate, project checks, and real upgrade verification.
- For an already public version, use a new patch version; it is prohibited to move the original tag or overwrite the original binary, signature, or manifest. Even re-uploading as a Draft only requires first confirming it is still a Draft, freezing the candidate, and re-accepting it; you must not check the status only after uploading.
- After passing the five-question self-check (or an authorized and evidence-backed exception to hotfix frequency), tag the final verified commit with a new tag and generate a Draft.
- Verify the installer, updater, standard signature verification, manifest, and actual running version; clarify whether old clients need to be manually overwritten once first, and finally make it public according to existing authorization. The complete contract is in Real Upgrade and Hotfix Gate。
Mode B: monorepo multi-component batch release
Applicable: when there are N independently releasable subprojects under one repository (skill sets, CLI tool sets, npm package sets, etc.), and you want one tag to publish all subproject zips at the same time; it also supports expert suite zips defined by symlinks within the repository and expanded into real directories at Release time.
Prerequisite: the corresponding project must have in config/projects.yaml a type: monorepo-skills entry, paired with scripts/build-zips.sh + scripts/release-monorepo.sh. When enabling the expert suite, also configure expert_suites_root and use validate-expert-suites.py + build-suite-zips.sh; for the complete SOP see references/monorepo-release.md。
Key differences from Mode A(relative to single-repository single-application):
| Dimension | Mode A (single application) | Mode B (monorepo) |
|---|---|---|
| tag frequency | 1 tag per application | 1 tag per release round (commonly CalVer) |
| zip naming | <App>-<ver>.<ext> |
<skill>-<semver>.zip; the suite is suite-<id>-<semver>.zip |
| Release Notes | Single-app changelog | N skill changelogs merged |
| Verification | Platform matrix (win/mac/linux) | Sub-project count list + spot checks on key items |
| Write back to README | Not applicable | Yes (write the latest URL into the table) |
Core process(see details in references/monorepo-release.md):
- Read the
projects.yamlentry of<project-key>, obtainskills_root、expert_suites_root、output_dir、exclude_globs - Run
build-zips.sh <tag>to generate the single Skill ZIP; when an expert suite exists, then run static validation andbuild-suite-zips.sh <tag> - Tag, push tag
- GitHub Actions (release.yml) automatically: upload the single Skill ZIP + expert suite ZIP + generate Release Notes (including the "Expert Suite" list section) + inline README write-back(checkout main → call
scripts/update-readme.pyto sync the root README withexpert-suites/*/README.mddownload links → commit + push) - Verify that the number of assets on the release page = number of single Skill ZIPs + number of suite ZIPs; the total number of skills in Release Notes is taken from the artifact directory but excludes the
suite-*prefix, and the suite count is rendered separately with{suites}.
README write-back does not depend on the
on: releaseevent — Releases created by GITHUB_TOKEN are subject to GitHub's anti-recursion mechanism and will not cascade to trigger other workflows (in practice this has never worked).update-readme.ymlusesworkflow_run(after the Release workflow succeeds) +workflow_dispatchas a fallback, and calls the samescripts/update-readme.pyas release.yml; there is no second copy of the logic; when triggered by workflow_run, checkout explicitlyref: main(by default it checks out to the tag SHA's detached HEAD, and the push fails).
The download link check must match the full asset path of the actual download column href; the correct URL in the body must not be used to mask an incorrect link. Source checks do not prove the asset exists without network access; retained public links should first be verified against the real Release assets, and do not use align-suite-links.py to change the source README to a download for a version that does not yet exist.
- Strict by default:
validate-expert-suites.pywithout a mode still requires the current version download entry;--mode releaseis the same strict check. - Source/prebuild: explicit
--mode sourceallows a real older version entry, but the member role column must accurately state;源码 v<当前版本> 待发布; when there is not yet a public member package, write尚无公开下载in the download column. If a complete set of old packages already exists, use a separate row> 整套源码 v<当前版本> 待发布; for a suite not yet released for the first time, use> 整套源码 v<当前版本> 待首次发布(尚无公开下载), and do not add a placeholder URL for a future ZIP. Checks on members, licenses, Git tracking, name, version, and link boundaries are not downgraded. - Preview:
SUITE_BUILD_MODE=preview bash scripts/build-suite-zips.sh pr-<编号>, expand the same source snapshot and retain the real public link/to-be-released note; do not describe a PR preview as a GitHub Release download. - Local Release staging: first generate the current member ZIP, then build the suite in the default
releasemode. The staging renderer verifies the complete file set and per-file bytes of the member ZIP, rejects symlinks/duplicate files, and then rewrites only the current tag and actual member version in a temporary directory. The source worktree and.gitattributesmust be consistent withSOURCE_REF; on failure, do not overwrite the previous batch of suite packages. This local build does not perform upload or release; the official release still follows the original authorization gate.
The expert suite members use the relative symlink of expert-suites/<id>/skills/* as the sole build manifest, and do not add suite.yamlThe builder first verifies that links have not escaped, that the README member table is consistent, and that member licenses are complete, then exports the real Skill directory from the specified Git tree; symbolic links must not be retained in the Release ZIP.
README structural synchronization (must be checked at release time; the parts that write-back cannot cover): automatic write-back only handles the links and version columns of existing table rows;adding rows, section assignment, descriptionsare structural maintenance and must be completed manually/by AI during the release step—
- Run
scripts/check-readme-coverage.py: every Release asset must have a row and a download link in the README skill table (standalone repository rows are exempt); a missing row means a new skill/migrated skill has not been synchronized to the README—add the row before releasing, or add it immediately after releasing - Section assignment self-check: a row's section must match the nature of the skill—general-purpose tool categories (expense organization, check-in, retrospective, etc.) do not go in the "Legal Professional Applications" section; the category label (column 2), the license, and the SKILL.md description must corroborate one another
- The description must be consistent with the
skills/<name>/SKILL.mdfrontmatter and must not be fabricated
Do not use for: single-application desktop/CLI/Web projects (use the 7-step process in Mode A above), cross-repository distribution (use the subtree-publish skill).
Required permissions and side effects
- Local Preview only reads the current Git tree and writes a ZIP to the repository's
pack-skills/; it does not create tags, access the network, install dependencies, or modify the README. - The official release reads Git status, executes
git fetch, creates an annotated tag, pushes the verified immutable tag OID toorigin, and reads Actions and Release status viagh. Before execution, the Release Five Questions must be completed andRELEASE_CONFIRMED=1。 - The official release may only be executed from a clean, non-detached main working tree whose HEAD matches
origin/main; an existing local or remote tag with the same name, missing identity, CI failure, or asset count mismatch all fail closed. RELEASE_GIT_NAMEandRELEASE_GIT_EMAILcan explicitly bind the tagger identity; when unset, the current Git identity is read, but empty fields will block.- Download link write-back is performed by
contents: writewith onlyupdate-readme.ymlpermissions after the release workflow succeeds; the local release script does not commit or push branches. - The script only accesses the current GitHub repository and its Actions/Release API, and does not read the contents of cloud service credentials; the Token is managed by GitHub Actions or
ghitself and is not written to artifacts or logs.
Release process
Step 1: Determine the version number
Obtain the target version number from the user or read it from CHANGELOG.md.
Unify all version number files (choose according to project type):
- Node.js projects:
package.json→version - Rust projects:
Cargo.toml→version - Python projects:
pyproject.toml→version - Desktop applications: the corresponding configuration file (e.g., Tauri's
tauri.conf.json) - CHANGELOG.md → latest
## [x.y.z]entry
Version number rules (SemVer):
| Type | Example | Applicable scenario |
|---|---|---|
| PATCH | 0.3.7 → 0.3.8 | Bug fixes, minor improvements |
| MINOR | 0.3.x → 0.4.0 | New features, backward compatible |
| MAJOR | 0.x → 1.0.0 | Major architectural changes, breaking changes |
Step 2: Generate Release Notes
There are two sources of information, and both must be used together:
Source 1 — CHANGELOG.md: structured change categories (Added / Changed / Fixed, etc.)
Source 2 — git log: commit history between two tags, supplementing context and details
# 获取上一个 tag
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
# 查看 commit 历史
git log ${PREV_TAG}..HEAD --oneline
# 查看详细变更(含 PR 链接)
git log ${PREV_TAG}..HEAD --format="- %s (%h)"
Source 3 — PR author information (external contributor identification):
# 本版本区间合入的 PR 与作者(识别需要致谢的外部贡献者)
gh pr list --state merged --limit 50 --json number,title,author \
--jq '.[] | "\(.number)\t\(.author.login)\t\(.title)"'
PRs from external contributors (non-maintainers) — including the original PR redone as "takes over #N" — must be acknowledged in the Release Notes: inline in the entry line (#N, @user) + the "Contributors" section at the end. For identification methods and format details, see references/release-notes-guide.md"Contributor Acknowledgments".
Combine the three sources and organize the Release Notes according to the template. For the template and format guide, see references/release-notes-guide.md. If config/projects.yaml contains release_notes.profile, prioritize the structure specified by the project configuration; when not configured, choose the default structure based on the project type.
Step 3: Commit and Tag
# 确保所有变更已提交
git status
# 打 tag
git tag "vX.Y.Z"
# ⚠️ 必须校验:tag 指向的 commit 包含版本号同步 commit。
# 重打 hotfix 时常见坑:只改了 release.yml 没把 4 处版本号文件也升到 X.Y.Z,
# 导致产物文件名仍带旧版本号(如 Folia_0.4.0_* 但 tag 是 v0.4.1)。
git show vX.Y.Z --stat | head -20
# 确认 package.json / Cargo.toml / tauri.conf.json / CHANGELOG.md 都在 commit 里
# 推送 tag 触发 CI
git push origin "vX.Y.Z"
If a tag with the same name already exists, first verify its full OID, Release status, and user visibility. Do not delete and re-tag an already public tag. For code fixes, use a new patch; for transient build failures of a fixed candidate, the same workflow may be rerun, but evidence must still be retained. For re-uploading assets of an unpublished Draft, follow Hotfix Gate when executing.
Step 4: Monitor CI Build
# 查看构建状态
gh run list --limit 3
# 各平台 job 状态
gh run view <RUN_ID> --json jobs --jq '.jobs[] | "\(.name): \(.conclusion)"'
# 失败日志
gh run view <RUN_ID> --log-failed
For build artifacts and verification methods specific to the project type, see the corresponding documentation under references/ .
Step 5: Update Release Notes
After the CI build succeeds, update the GitHub Release using the draft prepared in Step 2:
gh release edit vX.Y.Z --repo <owner>/<repo> --notes "$(cat <<'EOF'
<Release Notes 内容>
EOF
)"
Do not write # <项目名> vX.Y.Z or other duplicate version titles in the Release Notes body; the GitHub Release page itself already displays the title, so the body should start directly with the summary, upgrade notes, or Highlights.
Step 6: Verify
# 检查产物是否完整
gh release view vX.Y.Z --json assets --jq '.assets[].name'
Check against the configuration for this project in config/projects.yaml :
- Whether the expected artifacts are complete (derived from
platformsandauto_update) exclude_assetsWhether artifacts listed in- have unexpectedly appeared
- Whether the Release Notes comply with the
release_notes.required_sectionsandrelease_notes.always_includeconstraints - When this version includes PRs from external contributors, whether the Release Notes include acknowledgments (inline annotations or a "Contributors" section)
- Artifact completeness matrix cross-check(mandatory for projects with auto-update): see the table below, check off each row against the artifact list
| Platform | Installer | updater binary | .sig | latest.json entry |
|---|---|---|---|---|
| darwin-aarch64 | App_X.Y.Z_aarch64.dmg |
App_aarch64.app.tar.gz |
App_aarch64.app.tar.gz.sig |
darwin-aarch64 |
| darwin-x86_64 | App_X.Y.Z_x64.dmg |
App_x64.app.tar.gz |
App_x64.app.tar.gz.sig |
darwin-x86_64 |
| windows-x86_64 | App_X.Y.Z_x64-setup.exe |
(included with NSIS) | App_X.Y.Z_x64-setup.exe.sig |
windows-x86_64 |
The original macOS artifact and the uploaded filename may differ (for example, Fathom adds the version number before uploading); defer to the project configuration and actual assets, and the manifest URL must match the final name verbatim. Publishing is prohibited if any required item is missing; after fixing the configuration/code, re-verify, and use a new patch for already public versions. Complete assets and JSON validation do not equal cryptographic signature verification or a successful real upgrade; continue to execute Upgrade Gate。
Step 7: Cleanup
- Retain failure logs and artifacts needed for diagnostics; deleting Actions runs / Drafts requires separately verifying the target, ownership, and existing authorization
- Do not delete or overwrite the tag / binaries / signatures / manifest of an already public version
- Confirm whether mirror synchronization succeeded (if configured)
Project Type-Specific Guides
| Project Type | Reference Documentation |
|---|---|
| Tauri desktop application | references/tauri-release.md |
Checklist
Before tagging (mandatory) — see above ## ⚠️ Release ≠ 测试 — 强制约束:
- This is installed for real users, not just to show yourself the artifact
- The CHANGELOG has structured entries for this version
- At least 24 hours since the last tag, or evidence of a real blocking hotfix and explicit authorization has been recorded
- This release has ≥ 1 substantive fix / feature / change
- Passed the five-question self-check
After the release is complete, confirm:
- All platform / matrix builds succeeded
- GitHub Release artifacts are complete
- Release Notes have been updated, and the body has no duplicate version heading
- External contributors have been thanked in the Release Notes (when this version includes merged external PRs, including the original PRs that were adopted)
- The README skill list has been synchronized:
check-readme-coverage.pyPassed (no missing lines/missing links), section attribution and descriptions are correct (see pattern B "README structural synchronization") - Mirror synchronization succeeded (if configured)
- The auto-update project has completed standard signature verification and a real upgrade/failure recovery, and the old client manual guidance is accurate
- Diagnostic evidence is retained, and cleanup is limited to authorized targets
- Project documentation has been updated (TASKS / DECISIONS / CHANGELOG, etc.)
- The tag points to the correct commit