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
13 changes: 13 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

# Cargo.toml on develop still carries whatever release-please last wrote on
# master, so an RC would otherwise report that stale version in
# `rtk --version`, in telemetry, and in the .deb/.rpm filenames.
- name: Stamp version from tag
shell: bash
run: bash scripts/version-from-tag.sh "${{ inputs.tag }}"

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
Expand Down Expand Up @@ -112,6 +119,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Stamp version from tag
run: bash scripts/version-from-tag.sh "${{ inputs.tag }}"

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

Expand All @@ -138,6 +148,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Stamp version from tag
run: bash scripts/version-from-tag.sh "${{ inputs.tag }}"

- name: Install dependencies
run: |
dnf install -y rust cargo rpm-build
Expand Down
5 changes: 4 additions & 1 deletion CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,13 @@ Three edits to `release.yml` and `next-release.yml` are deliberately **not** For

- the repo guard on the Discord and Homebrew jobs (a fork must never be able to write to upstream's tap or announce in upstream's Discord),
- the GitHub App token falling back to `GITHUB_TOKEN` when no App is installed (without it, the entire release run fails on any fork),
- the `permissions` block `next-release.yml` needs for that fallback to have any rights at all.
- the `permissions` block `next-release.yml` needs for that fallback to have any rights at all,
- stamping `Cargo.toml`'s version from the release tag at build time, so an RC does not report the stale version release-please last wrote on `master` (upstream's own RCs ship `rtk_0.42.4-1_amd64.deb` for the same reason; on a fork that filename additionally collides byte-for-byte with upstream's artifact).

The distinction is the test, not the file: an edit lands in the table above only when upstream would have no reason to want it.

**Deferred Upstream PRs.** The obligation does not expire because a fix is convenient to keep. When the maintainer defers submission — batching, timing, not wanting to flood upstream — the fix is recorded as owed, not quietly reclassified as Fork Infrastructure. An Original fix sitting unsubmitted is divergence the fork is carrying on upstream's behalf, and the fork should know how much of it there is.

**Release track**:
The fork publishes on two. **RC** — every push to `develop` builds `fork-dev-X.Y.Z-rc.N`, automatic and continuous, for the maintainer and anyone wanting the tip. **Stable** — `fork-vX.Y.Z`, cut by merging the accumulated `develop → master` PR when the maintainer judges there is enough, and the only track a visitor is pointed at. Fork versions restart at `0.1.0` and never track upstream's numbers; the upstream base is stated in the release notes, never encoded in the version.
_Avoid_: pre-release (ambiguous — upstream uses it for its own `dev-*` tags)
Expand Down
73 changes: 73 additions & 0 deletions scripts/version-from-tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
#
# Stamp Cargo.toml's package version from the release tag being built.
#
# Cargo.toml on develop carries whatever version release-please last wrote on
# master, so every RC built from develop reports that stale number: an RC tagged
# fork-dev-0.1.0-rc.9 shipped `rtk_0.42.4-1_amd64.deb` and `rtk --version` said
# 0.42.4. Upstream has the same behaviour, but for a fork it is worse — that
# filename is byte-identical to upstream's own RC artifact, so two different
# binaries share one package identity.
#
# CARGO_PKG_VERSION feeds `rtk --version`, telemetry, cargo-deb, and
# cargo-generate-rpm, so stamping it once here fixes all four.
#
# Usage: scripts/version-from-tag.sh <tag> [cargo-toml-path]
# scripts/version-from-tag.sh --test
set -euo pipefail

# fork-dev-0.1.0-rc.9 -> 0.1.0-rc.9 fork-v0.1.0 -> 0.1.0
# dev-0.44.2-rc.344 -> 0.44.2-rc.344 v0.44.1 -> 0.44.1
version_from_tag() {
local v="$1"
v="${v#fork-}"
v="${v#dev-}"
v="${v#v}"
printf '%s' "$v"
}

if [ "${1:-}" = "--test" ]; then
fail=0
check() {
local got
got="$(version_from_tag "$1")"
if [ "$got" = "$2" ]; then
echo " ok $1 -> $got"
else
echo " FAIL $1 -> $got (expected $2)"
fail=1
fi
}
check "fork-dev-0.1.0-rc.9" "0.1.0-rc.9"
check "fork-v0.1.0" "0.1.0"
check "fork-v1.2.3" "1.2.3"
check "dev-0.44.2-rc.344" "0.44.2-rc.344"
check "v0.44.1" "0.44.1"
exit $fail
fi

TAG="${1:?usage: version-from-tag.sh <tag> [cargo-toml-path]}"
MANIFEST="${2:-Cargo.toml}"

VERSION="$(version_from_tag "$TAG")"

# Refuse anything cargo would reject, rather than corrupting the manifest and
# failing later with a confusing parse error.
if ! printf '%s' "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
echo "::error::Tag '$TAG' does not yield a semver version (got '$VERSION')" >&2
exit 1
fi

[ -f "$MANIFEST" ] || { echo "::error::$MANIFEST not found" >&2; exit 1; }

# Only the first `version =` — that is the [package] one. Dependency versions
# appear later in the file and must not be touched.
sed -i "0,/^version = \".*\"/s//version = \"${VERSION}\"/" "$MANIFEST"

STAMPED="$(grep -m1 '^version = ' "$MANIFEST" | sed 's/version = "\(.*\)"/\1/')"
if [ "$STAMPED" != "$VERSION" ]; then
echo "::error::Failed to stamp $MANIFEST (it reads '$STAMPED', wanted '$VERSION')" >&2
exit 1
fi

echo "Stamped $MANIFEST version = $VERSION (from tag $TAG)"
Loading