From 698b86f89f843d7c36680a7f272e09d71cefa22d Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Mon, 31 Aug 2026 04:42:41 +0000 Subject: [PATCH 1/2] =?UTF-8?q?ci:=20dev=20=E2=86=92=20main=20=E2=86=92=20?= =?UTF-8?q?release=20promotion=20flow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a `dev` integration branch and wire the pipeline for a dev → main → cut-release (v* tag) → prod promotion flow: - container.yml: publish per stage — dev branch -> :dev (preview), main branch -> :staging (promoted/pre-release), v* tag -> prod (:latest/:beta/:); every build keeps an immutable :sha- tag. Verify the matching anonymous manifest per stage. - ci.yml + runner-policy.yml: also run on `dev` pushes (PRs already run regardless of base). - ReleaseProcess.md: document the branching model and the tag re-mapping. Note: `…:dev` now follows the `dev` branch; a deployment that tracked `…:dev` for "latest main" should repoint to `…:staging`. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01GKifWkRa73PGrp9acFWeyd --- .github/workflows/ci.yml | 2 +- .github/workflows/container.yml | 15 +++++++++++---- .github/workflows/runner-policy.yml | 2 +- documentation/ReleaseProcess.md | 26 ++++++++++++++++++++++++-- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0213b6..39f8197 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [main] + branches: [main, dev] paths-ignore: - "*.md" - "docs/**" diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index f0069c0..903ae81 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -2,7 +2,7 @@ name: Container publication on: push: - branches: [main] + branches: [main, dev] tags: ['v*'] workflow_dispatch: @@ -34,12 +34,19 @@ jobs: id: tags shell: bash run: | + # Promotion flow: dev branch -> :dev (preview), main branch -> + # :staging (promoted, pre-release), v* tag -> prod (:latest/:beta/:). + # Every build also gets an immutable :sha- tag. if [[ "$GITHUB_REF_TYPE" == tag ]]; then case "$GITHUB_REF_NAME" in v[0-9]*) ;; *) exit 1 ;; esac printf 'tags=%s\n' "$IMAGE:$GITHUB_REF_NAME,$IMAGE:latest,$IMAGE:beta,$IMAGE:sha-$GITHUB_SHA" >> "$GITHUB_OUTPUT" - else - test "$GITHUB_REF_NAME" = main + elif [[ "$GITHUB_REF_NAME" == main ]]; then + printf 'tags=%s\n' "$IMAGE:staging,$IMAGE:sha-$GITHUB_SHA" >> "$GITHUB_OUTPUT" + elif [[ "$GITHUB_REF_NAME" == dev ]]; then printf 'tags=%s\n' "$IMAGE:dev,$IMAGE:sha-$GITHUB_SHA" >> "$GITHUB_OUTPUT" + else + echo "container publication is not configured for ref $GITHUB_REF_NAME" >&2 + exit 1 fi - name: Build and publish the destination image once uses: docker/build-push-action@v7 @@ -57,7 +64,7 @@ jobs: # bootstrap; this anonymous pull is the fail-closed enforcement. - name: Verify the anonymous destination manifest run: | - if [[ "$GITHUB_REF_TYPE" == tag ]]; then tag="$GITHUB_REF_NAME"; else tag=dev; fi + if [[ "$GITHUB_REF_TYPE" == tag ]]; then tag="$GITHUB_REF_NAME"; elif [[ "$GITHUB_REF_NAME" == main ]]; then tag=staging; else tag=dev; fi token=$(curl -fsS 'https://ghcr.io/token?service=ghcr.io&scope=repository:thedancingdeveloper-org/rusttorrent:pull' | jq -r .token) test -n "$token" curl -fsS -H "Authorization: Bearer $token" \ diff --git a/.github/workflows/runner-policy.yml b/.github/workflows/runner-policy.yml index 65a1c1f..5f3bc1f 100644 --- a/.github/workflows/runner-policy.yml +++ b/.github/workflows/runner-policy.yml @@ -9,7 +9,7 @@ name: Runner policy on: pull_request: push: - branches: [main] + branches: [main, dev] jobs: runner-policy: diff --git a/documentation/ReleaseProcess.md b/documentation/ReleaseProcess.md index 1ffe971..04bbc94 100644 --- a/documentation/ReleaseProcess.md +++ b/documentation/ReleaseProcess.md @@ -11,6 +11,28 @@ The current beta release is `0.1.0-beta.3`. - Release tag: `v0.1.0-beta.3` - Docker tag: `ghcr.io/thedancingdeveloper-org/rusttorrent:v0.1.0-beta.3` +## Branching model + +Promotion flow: **`dev` → `main` → cut release (`v*` tag) → prod.** + +- **`dev`** is the integration branch. Feature/dependency PRs target `dev`. + Pushing `dev` runs CI and publishes the preview image + `ghcr.io/thedancingdeveloper-org/rusttorrent:dev` (+ immutable `sha-`). +- **`main`** is the promoted, pre-release branch. Promote `dev → main` by PR. + Pushing `main` runs CI and publishes `…:staging` (+ `sha-`) and + deploys the website. `main` is protected and its version stays at the current + beta until a release is cut. +- **`v*` tag** (cut from `main`) is the release lever → prod: builds the + binaries + `.deb`, publishes them to the download host and the GitHub release, + and publishes the multi-arch prod image tagged `…:`, `…:latest`, `…:beta` + (+ `sha-`). + +Nothing auto-deploys the running prod service from these workflows; publication +is to GHCR + the download host, and the deployment platform (Komodo) pulls the +tag it is configured for. A deployment that previously tracked `…:dev` for +"latest main" must repoint to `…:staging`, since `…:dev` now follows the `dev` +branch. + ## CI Flow Pushes and tags run the workflows under `.github/workflows/`. @@ -18,8 +40,8 @@ Pushes and tags run the workflows under `.github/workflows/`. The Rust workflow builds the workspace from GitHub. Local development keeps `[patch]` sections pointed at sibling crates under `../libs/`. -Main branch pushes publish the public GHCR image as `dev` and an immutable -`sha-` tag. +`dev` branch pushes publish the GHCR image as `dev`; `main` branch pushes +publish it as `staging`; both add an immutable `sha-` tag. Release tags build: From 79b36a38ea327acae583bfc0ba8501bd92f674e9 Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Mon, 31 Aug 2026 04:44:23 +0000 Subject: [PATCH 2/2] ci(dependabot): target the dev branch for version updates Point all six Dependabot update configs at `dev` so dependency PRs land on the integration branch and promote to main via the normal flow. Takes effect once this reaches the default branch (main). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01GKifWkRa73PGrp9acFWeyd --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1213deb..dfb5515 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,6 +8,7 @@ updates: # ---- Rust: main workspace (covers all crates/* and desktop/src-tauri) ---- - package-ecosystem: cargo directory: "/" + target-branch: "dev" schedule: interval: weekly open-pull-requests-limit: 10 @@ -20,6 +21,7 @@ updates: # ---- Rust: benchv2 (excluded from the workspace) ---- - package-ecosystem: cargo directory: "/benchv2" + target-branch: "dev" schedule: interval: weekly open-pull-requests-limit: 5 @@ -32,6 +34,7 @@ updates: # ---- Rust: fuzz (excluded from the workspace) ---- - package-ecosystem: cargo directory: "/fuzz" + target-branch: "dev" schedule: interval: weekly open-pull-requests-limit: 5 @@ -44,6 +47,7 @@ updates: # ---- npm: web UI (crates/librtbit/webui) ---- - package-ecosystem: npm directory: "/crates/librtbit/webui" + target-branch: "dev" schedule: interval: weekly open-pull-requests-limit: 10 @@ -56,6 +60,7 @@ updates: # ---- npm: root workspace (includes the desktop package) ---- - package-ecosystem: npm directory: "/" + target-branch: "dev" schedule: interval: weekly open-pull-requests-limit: 5 @@ -68,6 +73,7 @@ updates: # ---- GitHub Actions workflows ---- - package-ecosystem: github-actions directory: "/" + target-branch: "dev" schedule: interval: weekly open-pull-requests-limit: 5