Skip to content

Latest commit

 

History

History
307 lines (251 loc) · 11.6 KB

RELEASING.md

File metadata and controls

307 lines (251 loc) · 11.6 KB

Releasing the maintained fork

Forgejo at https://forgejo.argentwolf.org/alan/activity-relay is the repository and release authority. GitHub is a downstream public mirror and independent-validation surface; mirrored commits or tags must not cause GitHub to publish release artifacts or mutable container tags.

The current GitHub release workflow is deliberately manual and validation-only. Forgejo owns the manual canonical release-artifact build and the authoritative exact-byte publication path proven during the 3.0 RC cycle. The build accepts only an exact reviewed commit and version and does not publish by itself. Do not tag a new release until that workflow has passed on the exact release-preparation commit, its retained artifact set has been inspected, and the accepted bytes are identified for publication. Do not tag merely to exercise either workflow.

Version and tag policy

  • Patch release: backward-compatible fixes, for example 2.5.1.
  • Minor release: backward-compatible features, for example 2.6.0.
  • Major release: incompatible configuration, API, storage, protocol, or identity changes.
  • Release candidate: append -rcN, for example v2.6.0-rc1.

Prerelease tags publish only their complete prerelease container tag. They do not move latest, major, or major/minor tags.

The workflow derives the Debian version series from the tag and preserves the top changelog version when it already belongs to that series. Debian packaging metadata and application identity are intentionally distinct: Debian revisions and prerelease ordering syntax must never leak into relay --version, /status.json, or activity_relay_build_info. The stable v3.0.0 release uses:

3.0.0-1

A future prerelease such as v2.6.0-rc1 uses a Debian series such as 2.6.0~rc1-1. If the top changelog entry does not match the tag series, the workflow starts that series at Debian revision -1.

Release filenames replace ~ with - in public artifact filenames; the package's internal Debian version is unchanged.

Release checklist

  1. Work from a clean master branch.
  2. Review AGENTS.md, ARCHITECTURE.md, and TODO.md.
  3. Update CHANGELOG.md, readme.md, affected deployment documentation, and the versioned release notes under docs/releases/.
  4. Confirm no local notes, generated packages, suspicious filenames, or machine-specific paths are tracked.
  5. Validate the Compose preflight behavior with missing, directory-valued, and valid actor.pem files.
  6. Run gofmt on changed Go files.
  7. Run go vet ./....
  8. Run Redis-backed go test -count=1 -p 1 ./....
  9. Run Redis-backed go test -race -count=1 -p 1 ./....
  10. Run python3 -m unittest discover -s contrib/web -p 'test_*.py'.
  11. Run python3 -m unittest discover -s contrib/ops -p 'test_*.py'.
  12. Validate the Caddy example when it changes.
  13. Run git diff --check.
  14. Build the local container and verify:
    • /usr/bin/relay;
    • /usr/share/activity-relay/web/build-site.py;
    • the compiled version string.
  15. Build the native Debian package, require the intended noble distribution in the .changes metadata, and run Lintian error validation on the binary .deb.
  16. Smoke-test /actor, /nodeinfo/2.1, and /status.json.
  17. Complete the applicable container and native-package matrix in docs/INTEGRATION-TESTING.md, retaining external evidence for the exact commit and artifacts.
  18. For task-transport changes, run the interruption matrix and confirm:
    • queued work survives pre-claim downtime;
    • graceful shutdown completes and acknowledges active work;
    • lease expiry recovers work after abrupt termination;
    • remote success followed by local pre-acknowledgement failure produces the expected at-least-once duplicate rather than silent loss;
    • delayed retries survive worker downtime; and
    • final ready, delayed, claim-payload, and claim-lease state is empty.
  19. Confirm the exact Machinery pseudo-version and commit in go.mod match the revision covered by local, CI, container, and package evidence.
  20. For publisher/fan-out changes, verify a real accepted publisher activity reaches a receiving server.
  21. Before stable promotion from a release candidate, complete a production soak of the exact candidate application code. Classify every observed failure as release-caused, receiver-caused, or environmental, and retain the evidence outside the public repository.
  22. Commit and push the release preparation to the authoritative Forgejo repository.
  23. Run the manual canonical Forgejo release-artifact workflow against the exact reviewed commit and version. Inspect its public artifacts and retained evidence, and verify every checksum.
  24. Confirm an exact-byte publication path exists for that artifact set. Do not rebuild the Debian package or OCI archive after acceptance. If exact-byte promotion is not available, stop.
  25. Create and push the annotated tag to Forgejo only after the accepted canonical bytes are identified unambiguously.
  26. Publish those exact accepted bytes and only the reviewed versioned release notes for that artifact set.
  27. Verify the canonical published release, checksums, package metadata, packaged examples, container manifests, and downstream mirror propagation.

Local validation

Use a disposable Redis instance:

docker rm -f activity-relay-release-test-redis \
  >/dev/null 2>&1 || true

docker run \
  --detach \
  --rm \
  --name activity-relay-release-test-redis \
  --publish 127.0.0.1:6381:6379 \
  redis:7-alpine

until docker exec activity-relay-release-test-redis redis-cli ping |
  grep -qx PONG
do
  sleep 1
done

REDIS_URL='redis://127.0.0.1:6381' \
  go test -count=1 -p 1 ./...

REDIS_URL='redis://127.0.0.1:6381' \
  go test -race -count=1 -p 1 ./...

go vet ./...

python3 -m unittest discover \
  -s contrib/web \
  -p 'test_*.py'

python3 -m unittest discover \
  -s contrib/ops \
  -p 'test_*.py'

docker run --rm \
  --volume "$PWD/contrib/caddy/Caddyfile.example:/etc/caddy/Caddyfile:ro" \
  caddy:2.11.2-alpine \
  caddy validate \
    --config /etc/caddy/Caddyfile \
    --adapter caddyfile

docker rm -f activity-relay-release-test-redis

Build and inspect the container using the application version represented by the current Debian changelog entry:

DEB_VERSION="$(dpkg-parsechangelog -SVersion)"
APP_VERSION="${DEB_VERSION%%-*}"
APP_VERSION="${APP_VERSION//\~/-}"

ACTIVITY_RELAY_VERSION="$APP_VERSION" \
docker compose \
  -f compose.yml \
  -f compose.build.yml \
  build

docker run \
  --rm \
  activity-relay:local \
  --version

docker run \
  --rm \
  --entrypoint /bin/sh \
  activity-relay:local \
  -c '
    test -x /usr/bin/relay
    test -f /usr/share/activity-relay/web/build-site.py
    test -f /usr/share/activity-relay/web/site.json.example
    test -x /usr/bin/activity-relay-resource-guard
    test -x /usr/lib/activity-relay/resource-guard.py
  '

Build and inspect the Debian package:

DEB_VERSION="$(dpkg-parsechangelog -SVersion)"
DEB_UPSTREAM="${DEB_VERSION%-*}"
APP_VERSION="${DEB_UPSTREAM//\~/-}"
ARCH="$(dpkg --print-architecture)"

dpkg-buildpackage \
  --build=binary \
  --no-sign

changes="../activity-relay_${DEB_VERSION}_${ARCH}.changes"
package="../activity-relay_${DEB_VERSION}_${ARCH}.deb"

grep --quiet '^Distribution: noble$' "$changes"
lintian --fail-on error "$package"

extract="$(mktemp -d)"
trap 'rm -rf "$extract"' EXIT
dpkg-deb -x "$package" "$extract"
test "$("$extract/usr/bin/relay" --version)" = "relay version $APP_VERSION"

Canonical release artifact build

Before creating a release tag, dispatch Canonical Release Artifacts from Forgejo on the exact release-preparation commit. Supply:

expected_commit: <full 40-character reviewed commit>
version:         X.Y.Z or X.Y.Z-rcN
confirm:         BUILD <the exact version above>

The versioned release-notes file must record both:

- Application version: `X.Y.Z` or `X.Y.Z-rcN`
- Debian package version: `X.Y.Z-1` or `X.Y.Z~rcN-1`

The workflow must produce one retained deterministic activity-relay-canonical.tar containing the complete public/ and evidence/ trees. Verify public/SHA256SUMS, inspect BUILD-METADATA.txt, the Debian metadata and Lintian output, and the OCI index evidence. The OCI archive must contain both linux/amd64 and linux/arm64, and both exact archived images must report the requested application version when executed.

Forgejo's outer Actions artifact wrapper is transport only. It may rewrite ZIP entry timestamps and other metadata, so it is not a release identity or checksum authority. The deterministic tar carrier sorts members, normalizes UID/GID to zero, and sets member mtimes to the source_date_epoch already recorded in public/BUILD-METADATA.txt. Existing file modes are preserved. The workflow builds the carrier twice and requires byte identity before upload; the packaging script re-extracts the carrier and revalidates public/SHA256SUMS before returning success.

After downloading a Forgejo Actions artifact, extract its outer wrapper and then extract activity-relay-canonical.tar. Perform release acceptance and later publication from the resulting public/ assets rather than directly from the outer wrapper.

Passing this workflow means the canonical release bytes were built and retained; it does not mean they were tagged or published. Those are later gates.

Tag the tested commit

Do not create a new release tag until the canonical Forgejo release workflow has passed on the exact release-preparation commit, the retained bytes have been inspected, and the exact-byte publication path has been proven. Then tag only the exact reviewed Forgejo commit:

git switch master
git pull --ff-only origin master

git tag -s vX.Y.Z -m 'Activity-Relay vX.Y.Z'
git push origin vX.Y.Z

Promote a validated release candidate by creating a new stable preparation commit and a new stable vX.Y.Z tag. Never move or rename the published RC tag. For a future release candidate, use its complete vX.Y.Z-rcN tag and matching versioned release-notes file. Do not move an already-published release tag; correct mistakes with another release candidate or patch release.

Current workflow behavior

Forgejo push and pull-request CI is authoritative for source validation. It runs the serialized Redis-backed Go and race suites, Python tests, container and Caddy validation, and Debian package build/lint checks on the managed Forgejo runner pool.

The GitHub mirror retains independent source/container validation. Its former release workflow is manual and validation-only: it may validate an existing tag and retain ephemeral Actions artifacts, but it does not create GitHub Releases, push container images, or move mutable container tags.

.forgejo/workflows/release.yml is the manual canonical release build. It requires the exact reviewed commit, application version, and explicit BUILD <version> confirmation; re-runs source/package/container validation; emits one checksummed Debian package, CycloneDX SBOM, multi-architecture OCI archive, release-note copy, build metadata, and retained evidence tree; wraps that tree in one deterministic metadata-preserving tar carrier; and publishes nothing externally. The 3.0 RC1 and RC2 cycles exercised the exact-byte build/publication model; current releases additionally protect canonical file metadata from the Forgejo artifact transport layer.

Smoke tests

curl --fail --silent --show-error \
  http://127.0.0.1:8080/actor \
  >/dev/null

curl --fail --silent --show-error \
  http://127.0.0.1:8080/nodeinfo/2.1 \
  >/dev/null

curl --fail --silent --show-error \
  http://127.0.0.1:8080/status.json |
python3 -m json.tool