diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a165701..583aa3d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -117,20 +117,33 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # develop is a protected branch (required checks, no admin bypass), so a + # direct push of a fresh merge commit is rejected. When main only ever + # fast-forwards to green develop SHAs (see RELEASE_STRATEGY.md) develop + # already contains main and this job is a no-op. If main diverged anyway, + # open a back-merge PR instead of pushing. back-merge-develop: needs: create-release runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - name: Merge Main to Develop + - name: Back-merge main into develop (PR if diverged) + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - git config user.name "GitHub Actions" - git config user.email "actions@github.com" - git checkout develop - git merge origin/main - git push origin develop + git fetch origin develop main + if git merge-base --is-ancestor origin/main origin/develop; then + echo "develop already contains main — nothing to back-merge" + else + gh pr create --base develop --head main \ + --title "Back-merge main into develop after release" \ + --body "Automated post-release back-merge. If required checks did not start (GITHUB_TOKEN-created PRs do not trigger workflows), close and reopen this PR." \ + || echo "back-merge PR already exists" + fi diff --git a/docs/RELEASE_STRATEGY.md b/docs/RELEASE_STRATEGY.md index 4148aae..6d1c468 100644 --- a/docs/RELEASE_STRATEGY.md +++ b/docs/RELEASE_STRATEGY.md @@ -47,20 +47,30 @@ Automated pipelines run on every push to `main` or `develop`. ### Automated Release (Main-only) -Official releases are triggered ONLY from the `main` branch. +Official releases are triggered ONLY from the `main` branch. -1. **Tagging**: Push a semantic version tag to `main`: +Both `main` and `develop` are protected: the required checks are the *real* CI +jobs (`docker-validation`, `zephyr-validation`, `sbom-tools`) with no admin +bypass. Because a freshly created merge commit has no check results, release +promotion works by **fast-forwarding `main` to a develop SHA whose checks are +already green** — never by merging with a new commit. This keeps `main` an +exact subset of `develop`, so no back-merge is needed. + +1. **Promote + tag**: Fast-forward `main` to the green `develop` SHA and tag it: ```bash - git checkout main && git pull - git tag -a v1.0.0 -m "Release version 1.0.0" + git fetch origin + git push origin origin/develop:main # fast-forward; rejected if main diverged + git tag -a v1.0.0 -m "Release version 1.0.0" origin/develop git push origin v1.0.0 ``` 2. **Workflow**: The GitHub Action automatically: - Builds with **Code Coverage**. - Generates **Automated Release Notes**. - - Packages binaries and creates a GitHub Release. - - **Back-merges `main` to `develop`**. + - Packages binaries, **SBOMs (CycloneDX + SPDX)**, and creates a GitHub Release. + - **Back-merge safety net**: if `main` somehow diverged from `develop`, the + workflow opens a back-merge PR (it cannot push to the protected branch + directly). In the normal fast-forward flow this is a no-op. ### Release Candidates (RC)