Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9efe87b0b2 |
@@ -20,8 +20,8 @@ Current maintainers with PR approval authority: `theonlyhennygod`, `JordanTheJet
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `checks-on-pr.yml` | `pull_request` → `master` | Lint + test + build + security audit on every PR |
|
| `checks-on-pr.yml` | `pull_request` → `master` | Lint + test + build + security audit on every PR |
|
||||||
| `cross-platform-build-manual.yml` | `workflow_dispatch` | Full platform build matrix (manual) |
|
| `cross-platform-build-manual.yml` | `workflow_dispatch` | Full platform build matrix (manual) |
|
||||||
| `release-beta-on-push.yml` | `push` → `master` | Beta release on every master commit |
|
| `release-beta-on-push.yml` | `push` → `master` | Beta release on every master commit; **auto stable release + post-publish on version bumps** |
|
||||||
| `release-stable-manual.yml` | `workflow_dispatch` | Stable release (manual, version-gated) |
|
| `release-stable-manual.yml` | `workflow_dispatch` | Stable release fallback (manual, version-gated) |
|
||||||
|
|
||||||
## Event Summary
|
## Event Summary
|
||||||
|
|
||||||
@@ -55,14 +55,21 @@ Current maintainers with PR approval authority: `theonlyhennygod`, `JordanTheJet
|
|||||||
- `publish` job: generates `SHA256SUMS`, creates a GitHub pre-release with all artifacts. Artifact retention: 7 days.
|
- `publish` job: generates `SHA256SUMS`, creates a GitHub pre-release with all artifacts. Artifact retention: 7 days.
|
||||||
- `docker` job: builds multi-platform image (`linux/amd64,linux/arm64`) and pushes to `ghcr.io` with `:beta` and the versioned beta tag.
|
- `docker` job: builds multi-platform image (`linux/amd64,linux/arm64`) and pushes to `ghcr.io` with `:beta` and the versioned beta tag.
|
||||||
3. This runs on every push to `master` without filtering. Every merged PR produces a beta pre-release.
|
3. This runs on every push to `master` without filtering. Every merged PR produces a beta pre-release.
|
||||||
|
4. **If the push is a version bump** (Cargo.toml version changed from prior commit):
|
||||||
|
- `publish-stable` job: creates a stable (non-prerelease) GitHub Release with the `vX.Y.Z` tag. Replaces any existing release with that tag.
|
||||||
|
- `redeploy-website-stable` job: triggers website redeploy via repository dispatch.
|
||||||
|
- `tweet` job: calls `tweet-release.yml` to post the release announcement on X.
|
||||||
|
- `scoop` / `aur` / `homebrew` jobs: call their respective reusable workflows to update package manager manifests.
|
||||||
|
|
||||||
### 3) Stable Release (manual)
|
### 3) Stable Release (manual fallback)
|
||||||
|
|
||||||
|
> **Note:** This workflow now serves as a **fallback**. Version bump pushes to master automatically trigger stable releases via `release-beta-on-push.yml`. Use this workflow when you need to manually re-release or if the automated path failed.
|
||||||
|
|
||||||
1. Maintainer runs `release-stable-manual.yml` via `workflow_dispatch` with a version input (e.g. `0.2.0`).
|
1. Maintainer runs `release-stable-manual.yml` via `workflow_dispatch` with a version input (e.g. `0.2.0`).
|
||||||
2. `validate` job checks:
|
2. `validate` job checks:
|
||||||
- Input matches semver `X.Y.Z` format.
|
- Input matches semver `X.Y.Z` format.
|
||||||
- `Cargo.toml` version matches input exactly.
|
- `Cargo.toml` version matches input exactly.
|
||||||
- Tag `vX.Y.Z` does not already exist on the remote.
|
- If tag `vX.Y.Z` already exists, it warns and replaces the existing release (no longer fails hard).
|
||||||
3. `build` job (matrix, same 4 targets as beta): compiles release binary.
|
3. `build` job (matrix, same 4 targets as beta): compiles release binary.
|
||||||
4. `publish` job: generates `SHA256SUMS`, creates a stable GitHub Release (not pre-release). Artifact retention: 14 days.
|
4. `publish` job: generates `SHA256SUMS`, creates a stable GitHub Release (not pre-release). Artifact retention: 14 days.
|
||||||
5. `docker` job: pushes to `ghcr.io` with `:latest` and `:vX.Y.Z`.
|
5. `docker` job: pushes to `ghcr.io` with `:latest` and `:vX.Y.Z`.
|
||||||
@@ -100,25 +107,29 @@ flowchart TD
|
|||||||
E --> F["push event on master"]
|
E --> F["push event on master"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Beta Release (on every master push)
|
### Beta Release (on every master push) + Auto Stable on Version Bump
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["Push to master"] --> B["release-beta-on-push.yml"]
|
A["Push to master"] --> B["release-beta-on-push.yml"]
|
||||||
B --> B1["version: compute v{x.y.z}-beta.{N}"]
|
B --> B1["version: compute beta tag + detect version bump"]
|
||||||
B1 --> B2["build: 4 targets"]
|
B1 --> B2["build: 6 targets"]
|
||||||
B2 --> B3["publish: GitHub pre-release + SHA256SUMS"]
|
B2 --> B3["publish: GitHub pre-release + SHA256SUMS"]
|
||||||
B2 --> B4["docker: push ghcr.io :beta + versioned tag"]
|
B2 --> B4["docker: push ghcr.io :beta + versioned tag"]
|
||||||
|
B1 -->|"version bump detected"| S1["publish-stable: GitHub stable release"]
|
||||||
|
S1 --> S2["redeploy-website-stable"]
|
||||||
|
S1 --> S3["tweet: tweet-release.yml"]
|
||||||
|
S1 --> S4["scoop / aur / homebrew updates"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stable Release (manual)
|
### Stable Release (manual fallback)
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
A["workflow_dispatch: version=X.Y.Z"] --> B["release-stable-manual.yml"]
|
A["workflow_dispatch: version=X.Y.Z"] --> B["release-stable-manual.yml"]
|
||||||
B --> B1["validate: semver + Cargo.toml + tag uniqueness"]
|
B --> B1["validate: semver + Cargo.toml + warn if tag exists"]
|
||||||
B1 --> B2["build: 4 targets"]
|
B1 --> B2["build: 4 targets"]
|
||||||
B2 --> B3["publish: GitHub stable release + SHA256SUMS"]
|
B2 --> B3["publish: replace existing or create stable release"]
|
||||||
B2 --> B4["docker: push ghcr.io :latest + :vX.Y.Z"]
|
B2 --> B4["docker: push ghcr.io :latest + :vX.Y.Z"]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -126,5 +137,5 @@ flowchart TD
|
|||||||
|
|
||||||
1. **Quality gate failing on PR**: check `lint` job for formatting/clippy issues; check `test` job for test failures; check `build` job for compile errors; check `security` job for audit/deny failures.
|
1. **Quality gate failing on PR**: check `lint` job for formatting/clippy issues; check `test` job for test failures; check `build` job for compile errors; check `security` job for audit/deny failures.
|
||||||
2. **Beta release not appearing**: confirm the push landed on `master` (not another branch); check `release-beta-on-push.yml` run status.
|
2. **Beta release not appearing**: confirm the push landed on `master` (not another branch); check `release-beta-on-push.yml` run status.
|
||||||
3. **Stable release failing at validate**: ensure `Cargo.toml` version matches the input version and the tag does not already exist.
|
3. **Stable release failing at validate**: ensure `Cargo.toml` version matches the input version. Existing tags are now handled gracefully (warn + replace).
|
||||||
4. **Full matrix build needed**: run `cross-platform-build-manual.yml` manually from the Actions tab.
|
4. **Full matrix build needed**: run `cross-platform-build-manual.yml` manually from the Actions tab.
|
||||||
|
|||||||
@@ -1,6 +1,22 @@
|
|||||||
name: Pub Homebrew Core
|
name: Pub Homebrew Core
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
release_tag:
|
||||||
|
description: "Existing release tag to publish (vX.Y.Z)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
dry_run:
|
||||||
|
description: "Patch formula only (no push/PR)"
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
secrets:
|
||||||
|
HOMEBREW_UPSTREAM_PR_TOKEN:
|
||||||
|
required: false
|
||||||
|
HOMEBREW_CORE_BOT_TOKEN:
|
||||||
|
required: false
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
release_tag:
|
release_tag:
|
||||||
|
|||||||
@@ -26,8 +26,12 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.ver.outputs.version }}
|
version: ${{ steps.ver.outputs.version }}
|
||||||
tag: ${{ steps.ver.outputs.tag }}
|
tag: ${{ steps.ver.outputs.tag }}
|
||||||
|
is_version_bump: ${{ steps.bump.outputs.is_version_bump }}
|
||||||
|
stable_tag: ${{ steps.bump.outputs.stable_tag }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
- name: Compute beta version
|
- name: Compute beta version
|
||||||
id: ver
|
id: ver
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -39,6 +43,23 @@ jobs:
|
|||||||
echo "tag=${beta_tag}" >> "$GITHUB_OUTPUT"
|
echo "tag=${beta_tag}" >> "$GITHUB_OUTPUT"
|
||||||
echo "Beta release: ${beta_tag}"
|
echo "Beta release: ${beta_tag}"
|
||||||
|
|
||||||
|
- name: Detect version bump
|
||||||
|
id: bump
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
current=$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -1)
|
||||||
|
previous=$(git show HEAD~1:Cargo.toml 2>/dev/null | sed -n 's/^version = "\([^"]*\)"/\1/p' | head -1 || echo "")
|
||||||
|
|
||||||
|
if [[ "$current" != "$previous" && -n "$current" ]]; then
|
||||||
|
echo "is_version_bump=true" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "stable_tag=v${current}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Version bumped from ${previous} to ${current}"
|
||||||
|
else
|
||||||
|
echo "is_version_bump=false" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "stable_tag=" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
release-notes:
|
release-notes:
|
||||||
name: Generate Release Notes
|
name: Generate Release Notes
|
||||||
if: github.repository == 'zeroclaw-labs/zeroclaw'
|
if: github.repository == 'zeroclaw-labs/zeroclaw'
|
||||||
@@ -372,4 +393,104 @@ jobs:
|
|||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:beta-debian
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:beta-debian
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|
||||||
# Tweet removed — only stable releases should tweet (see tweet-release.yml).
|
# ── Stable release + post-publish (version bumps only) ────────────────
|
||||||
|
publish-stable:
|
||||||
|
name: Publish Stable Release
|
||||||
|
needs: [version, release-notes, build]
|
||||||
|
if: needs.version.outputs.is_version_bump == 'true'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||||
|
with:
|
||||||
|
pattern: zeroclaw-*
|
||||||
|
path: artifacts
|
||||||
|
|
||||||
|
- name: Generate checksums
|
||||||
|
run: |
|
||||||
|
cd artifacts
|
||||||
|
find . -type f \( -name '*.tar.gz' -o -name '*.zip' \) -exec sha256sum {} + | sed 's| \./[^/]*/| |' > SHA256SUMS
|
||||||
|
cat SHA256SUMS
|
||||||
|
|
||||||
|
- name: Collect release assets
|
||||||
|
run: |
|
||||||
|
mkdir -p release-assets
|
||||||
|
find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name 'SHA256SUMS' \) -exec cp {} release-assets/ \;
|
||||||
|
cp install.sh release-assets/
|
||||||
|
ls -lh release-assets/
|
||||||
|
|
||||||
|
- name: Write release notes
|
||||||
|
env:
|
||||||
|
NOTES: ${{ needs.release-notes.outputs.notes }}
|
||||||
|
run: printf '%s\n' "$NOTES" > release-notes.md
|
||||||
|
|
||||||
|
- name: Create or replace stable GitHub Release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
TAG: ${{ needs.version.outputs.stable_tag }}
|
||||||
|
run: |
|
||||||
|
# Remove existing release/tag if present (from prior partial run)
|
||||||
|
gh release delete "$TAG" --repo "${{ github.repository }}" --yes --cleanup-tag 2>/dev/null || true
|
||||||
|
|
||||||
|
gh release create "$TAG" release-assets/* \
|
||||||
|
--repo "${{ github.repository }}" \
|
||||||
|
--title "$TAG" \
|
||||||
|
--notes-file release-notes.md \
|
||||||
|
--latest
|
||||||
|
|
||||||
|
redeploy-website-stable:
|
||||||
|
name: Trigger Website Redeploy (Stable)
|
||||||
|
needs: [version, publish-stable]
|
||||||
|
if: needs.version.outputs.is_version_bump == 'true' && !cancelled() && needs.publish-stable.result == 'success'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Trigger website redeploy
|
||||||
|
env:
|
||||||
|
PAT: ${{ secrets.WEBSITE_REPO_PAT }}
|
||||||
|
run: |
|
||||||
|
curl -fsSL -X POST \
|
||||||
|
-H "Authorization: token $PAT" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
https://api.github.com/repos/zeroclaw-labs/zeroclaw-website/dispatches \
|
||||||
|
-d '{"event_type":"new-release","client_payload":{"install_script_url":"https://raw.githubusercontent.com/zeroclaw-labs/zeroclaw/master/install.sh"}}'
|
||||||
|
|
||||||
|
tweet:
|
||||||
|
name: Tweet Release
|
||||||
|
needs: [version, publish-stable, redeploy-website-stable]
|
||||||
|
if: needs.version.outputs.is_version_bump == 'true' && !cancelled() && needs.publish-stable.result == 'success'
|
||||||
|
uses: ./.github/workflows/tweet-release.yml
|
||||||
|
with:
|
||||||
|
release_tag: ${{ needs.version.outputs.stable_tag }}
|
||||||
|
release_url: https://github.com/zeroclaw-labs/zeroclaw/releases/tag/${{ needs.version.outputs.stable_tag }}
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
scoop:
|
||||||
|
name: Update Scoop Manifest
|
||||||
|
needs: [version, publish-stable]
|
||||||
|
if: needs.version.outputs.is_version_bump == 'true' && !cancelled() && needs.publish-stable.result == 'success'
|
||||||
|
uses: ./.github/workflows/pub-scoop.yml
|
||||||
|
with:
|
||||||
|
release_tag: ${{ needs.version.outputs.stable_tag }}
|
||||||
|
dry_run: false
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
aur:
|
||||||
|
name: Update AUR Package
|
||||||
|
needs: [version, publish-stable]
|
||||||
|
if: needs.version.outputs.is_version_bump == 'true' && !cancelled() && needs.publish-stable.result == 'success'
|
||||||
|
uses: ./.github/workflows/pub-aur.yml
|
||||||
|
with:
|
||||||
|
release_tag: ${{ needs.version.outputs.stable_tag }}
|
||||||
|
dry_run: false
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
homebrew:
|
||||||
|
name: Update Homebrew Core
|
||||||
|
needs: [version, publish-stable]
|
||||||
|
if: needs.version.outputs.is_version_bump == 'true' && !cancelled() && needs.publish-stable.result == 'success'
|
||||||
|
uses: ./.github/workflows/pub-homebrew-core.yml
|
||||||
|
with:
|
||||||
|
release_tag: ${{ needs.version.outputs.stable_tag }}
|
||||||
|
dry_run: false
|
||||||
|
secrets: inherit
|
||||||
|
|||||||
@@ -50,8 +50,7 @@ jobs:
|
|||||||
|
|
||||||
tag="v${input_version}"
|
tag="v${input_version}"
|
||||||
if git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null 2>&1; then
|
if git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null 2>&1; then
|
||||||
echo "::error::Tag ${tag} already exists."
|
echo "::warning::Tag ${tag} already exists — existing release will be replaced."
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
|
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
|
||||||
@@ -286,6 +285,12 @@ jobs:
|
|||||||
NOTES: ${{ needs.release-notes.outputs.notes }}
|
NOTES: ${{ needs.release-notes.outputs.notes }}
|
||||||
run: printf '%s\n' "$NOTES" > release-notes.md
|
run: printf '%s\n' "$NOTES" > release-notes.md
|
||||||
|
|
||||||
|
- name: Remove existing release if present
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
TAG: ${{ needs.validate.outputs.tag }}
|
||||||
|
run: gh release delete "$TAG" --repo "${{ github.repository }}" --yes --cleanup-tag 2>/dev/null || true
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
|||||||
Reference in New Issue
Block a user