Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,36 @@ jobs:
tagName: ${{ github.ref_name }}
releaseName: "AFKode ${{ github.ref_name }}"
releaseBody: "See the commit history for changes. Installers below; the updater feeds from latest.json."
releaseDraft: false
# Stays a draft until every matrix leg has actually finished — see
# the `publish` job below. Without this, if e.g. only Windows and
# Linux finish before macOS notarization fails, users could already
# be downloading (and the updater already pointing at) a release
# that's missing the macOS build entirely.
releaseDraft: true
prerelease: false
args: ${{ matrix.args }}

winget:
# Only flips the release public once every matrix leg above succeeded —
# `needs.release.result` reflects the matrix job as a whole (success only
# if every leg succeeded), not just the leg that happens to finish last.
# If any leg failed, this job is skipped and the draft is left exactly as
# it is — assets from whichever platforms did succeed, still private —
# for a human to inspect rather than either quietly going out partial or
# getting deleted.
publish:
needs: release
if: needs.release.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Make the release public
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release edit "${{ github.ref_name }}" --draft=false --repo ${{ github.repository }}

winget:
needs: publish
runs-on: windows-latest
# Requires the package to exist in winget-pkgs (initial PR merged);
# a failure here must not affect the release itself.
Expand Down
51 changes: 39 additions & 12 deletions .github/workflows/version-bump.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
name: Version Bump

# Runs after every push to main and decides, from Conventional Commits since
# the last tag, whether this merge deserves a new version: fix: -> patch,
# Runs after the "CI" workflow finishes on main, and only proceeds if it
# succeeded — never bump/tag/release a commit that doesn't even compile.
# (This used to run directly on `push: branches: [main]`, racing CI instead
# of waiting for it: a commit that failed to compile could still get bumped,
# tagged, and dispatched to release.yml, which would then fail after the
# tag was already public.)
#
# Once gated on a green CI run, it decides from Conventional Commits since
# the last tag whether this deserves a new version: fix: -> patch,
# feat: -> minor, a `!` after the type/scope or a `BREAKING CHANGE:` footer
# -> major. Anything else (chore/docs/refactor/test/ci/style, or a push with
# no new commits since the last tag) bumps nothing and the job exits early.
Expand All @@ -19,29 +26,49 @@ name: Version Bump
# release.yml via the API (`gh workflow run`), which release.yml has to
# opt into with `workflow_dispatch:`.
on:
push:
branches: [main]
workflow_run:
workflows: ["CI"]
types: [completed]

permissions:
contents: write
actions: write

# The bump commit's own push re-triggers "CI" (it runs on every push to
# main), which in turn re-triggers this workflow — the guard below turns
# that into a fast, harmless no-op (see it below), but two overlapping runs
# racing to push/tag at once would still be possible without this: e.g. a
# human push and the bump commit's CI run completing within moments of each
# other. Queue them instead of letting them interleave.
concurrency:
group: version-bump-main
cancel-in-progress: false

jobs:
bump:
runs-on: ubuntu-latest
# Without this, the bump commit's own push to main would re-trigger this
# same workflow. (In practice GITHUB_TOKEN pushes already don't trigger
# further runs — see the note above — but this keeps the job correct
# even if that ever changes, e.g. a maintainer force-pushing a manual
# bump commit under their own account.)
# The whole value must be quoted: an unquoted YAML scalar containing
# Only proceed for a green CI run on main — never for a failed/cancelled
# run, and never for CI runs from a PR branch (those also trigger "CI").
# The commit-message check is the same anti-recursion guard as before,
# now reading workflow_run's own head_commit instead of push's.
# The whole if: value must be quoted: an unquoted YAML scalar containing
# ": " (a colon followed by a space, as in 'chore: bump version to')
# gets parsed as a nested mapping key instead of plain text, which is
# an invalid workflow file GitHub Actions won't even schedule a job for.
if: "${{ !startsWith(github.event.head_commit.message, 'chore: bump version to') }}"
# an invalid workflow file GitHub Actions won't even schedule a job for
# (this exact bug broke this workflow's first real run).
if: >-
${{
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'main' &&
!startsWith(github.event.workflow_run.head_commit.message, 'chore: bump version to')
}}
steps:
- uses: actions/checkout@v4
with:
# Pin to the exact commit CI just validated, not whatever main's
# tip happens to be when this job starts — those should be the
# same commit, but pinning removes any doubt/race.
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0

- name: Determine bump level from commits since the last tag
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ portable-pty = "0.9"
tiny_http = "0.12"
base64 = "0.22"

[dev-dependencies]
# portable-pty's Child/MasterPty traits return anyhow::Error, but portable_pty
# only imports it privately (no public re-export) — needed by name to
# implement those traits for the fakes in lib.rs's test module. Already
# resolved transitively via portable-pty itself; this just makes it directly
# nameable from test code.
anyhow = "1"
# MasterPty::process_group_leader's #[cfg(unix)] signature returns
# Option<libc::pid_t> — same situation as anyhow above, needed by name only
# to implement the trait for the unix-only cfg branch of the test fakes.
libc = "0.2"

[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = [
"Win32_Foundation",
Expand Down
Loading
Loading