From ddbd9a48b3d519fc89f853601dc539b016da74f2 Mon Sep 17 00:00:00 2001 From: Justus-at-Tazama Date: Sat, 4 Apr 2026 22:47:25 +0200 Subject: [PATCH] feat: add scorecard and branch-target-check workflows - Add canonical scorecard.yml (OSSF Scorecard supply-chain security): - Triggers: push/[main,dev], schedule (weekly), branch_protection_rule - publish_results=true only on main/schedule/branch_protection_rule - Pinned to latest SHAs: checkout v6.0.2, scorecard-action v2.4.3, upload-artifact v7.0.0, codeql-action/upload-sarif v4.34.1 - All rule repos receive this file (no exclusions needed in frmscoe) - Add branch-target-check.yml: - Enforces dev->main and release/v.*->main PR targets - Rejects bare release/v (no version number) via release/v[0-9]* glob - Fails with actionable message and \gh pr edit --base dev\ hint - Copies to all repos (no exclusion needed) - Fixed github.head_ref injection risk (passed via env var) Mirror of tazama-lf/workflows#33 --- .github/workflows/branch-target-check.yml | 48 +++++++++++++++++++ .github/workflows/scorecard.yml | 58 +++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 .github/workflows/branch-target-check.yml create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/branch-target-check.yml b/.github/workflows/branch-target-check.yml new file mode 100644 index 0000000..bec2a31 --- /dev/null +++ b/.github/workflows/branch-target-check.yml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Enforces the feature-branch → dev → main development workflow. +# +# When `main` is the default branch, GitHub pre-selects it as the PR base in the +# UI and in `gh pr create`. This check fails immediately with a clear, actionable +# message if a PR targets main from any branch other than `dev` or `release/v.*`, +# saving developers from a confusing "branch is locked" error or a misleading +# "prerelease version detected" message from version-check.yml. +# +# Allowed sources for PRs to main: +# dev — the normal integration branch +# release/v.* — release-train branches created by release-train.yml (must start with a digit) +# +# Please do not attempt to edit this flow without the direct consent from the DevOps team. +# This file is managed centrally. + +name: Branch target check + +permissions: + contents: read + +on: + pull_request: + branches: + - main + +jobs: + check-source-branch: + if: github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' + runs-on: ubuntu-latest + steps: + - name: Verify PR source branch is dev or release/v.* + env: + SOURCE: ${{ github.head_ref }} + run: | + if [[ "$SOURCE" == "dev" || "$SOURCE" == release/v[0-9]* ]]; then + echo "✅ Source branch '$SOURCE' is a valid base for a PR to main." + else + echo "❌ PRs to main must come from 'dev' or a 'release/v.*' branch (e.g. release/v1.2)." + echo " This PR is from '$SOURCE'." + echo "" + echo " If you are working on a feature or fix, please retarget this PR to 'dev':" + echo " gh pr edit --base dev" + echo "" + echo " Only 'dev' → main (via release-train.yml) and 'release/v.*' → main merges are permitted." + exit 1 + fi diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..3a711fb --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Please do not attempt to edit this flow without the direct consent from the DevOps team. This file is managed centrally. + +name: Scorecard supply-chain security + +on: + branch_protection_rule: + schedule: + - cron: '15 16 * * 0' + push: + branches: + - main + - dev + +# Scorecard workflow restrictions (enforced when publish_results=true): +# - No workflow-level env vars or defaults +# - No workflow-level write permissions (read-all is fine) +# - Only the scorecard job may use id-token: write +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Required for uploading SARIF results to the code-scanning dashboard + security-events: write + # Required for GitHub OIDC token used by publish_results + id-token: write + + steps: + - name: "Checkout code" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + with: + results_file: results.sarif + results_format: sarif + # Publish results (badge + REST API) only when running on the default + # branch or on a schedule/branch-protection event. Dev-branch runs + # still score the repo but do not overwrite the published badge. + publish_results: ${{ github.ref == 'refs/heads/main' || github.event_name == 'schedule' || github.event_name == 'branch_protection_rule' }} + + - name: "Upload artifact" + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + with: + sarif_file: results.sarif