name: Port to release branch # Ports flagged commits from master onto stable-X.Y branches: # - "port 1.5" flag in a commit message pushed to master — own line or # mid-line; separators : / - or space; "stable-1.5" also accepted; # comma lists ("Port: 1.5, 1.4") work in the own-line form # - "port stable-1.5" label on a merged PR # Conflicts are reported to the "Port status: " tracking issue. on: push: branches: [master] pull_request_target: types: [closed, labeled] permissions: contents: write issues: write concurrency: group: port-engine cancel-in-progress: false jobs: port: name: Port flagged commits runs-on: ubuntu-latest steps: - name: Create GitHub App token id: app_token uses: actions/create-github-app-token@v2 with: app-id: ${{ secrets.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} # Base-repo code only; PR head code is never checked out or executed. - name: Checkout uses: actions/checkout@v6 with: ref: master fetch-depth: 0 token: ${{ steps.app_token.outputs.token }} - name: Port trailer-flagged commits if: github.event_name == 'push' env: GH_TOKEN: ${{ steps.app_token.outputs.token }} COMMITS: ${{ toJSON(github.event.commits) }} run: | set -euo pipefail git config user.name "dms-ci[bot]" git config user.email "dms-ci[bot]@users.noreply.github.com" for sha in $(jq -r '.[].id' <<<"$COMMITS"); do git cat-file -e "$sha" 2>/dev/null || continue # skip merge commits (handled by the label path) [ "$(git rev-list --no-walk --count --min-parents=2 "$sha")" -eq 0 ] || continue # own-line form (supports comma lists), validated version-shaped t1=$(git log -1 --format=%B "$sha" | { grep -iE '^Port[:/ -]' || true; } | sed -E 's|^port[-:/ ]+||I' | tr ',' '\n' | sed 's/[[:space:]]//g; /^$/d' | sed -E 's,^stable-,,I' | { grep -E '^[0-9]+\.[0-9]+(\.[0-9]+)?$' || true; }) # mid-line form, e.g. "fix thing fixes #2802 port 1.5" t2=$(git log -1 --format=%B "$sha" | { grep -oiE '\bport[-: /]+(stable-)?[0-9]+\.[0-9]+(\.[0-9]+)?\b' || true; } | sed -E 's|^port[-:/ ]+||I' | sed -E 's,^stable-,,I') targets=$(printf '%s\n%s\n' "$t1" "$t2" | sed '/^$/d' | sort -u) for ver in $targets; do echo "::group::port $sha -> stable-$ver" bash scripts/port.sh "stable-$ver" "$sha" echo "::endgroup::" done done - name: Port label-flagged PR if: > github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && (github.event.action == 'closed' || (github.event.action == 'labeled' && startsWith(github.event.label.name, 'port '))) env: GH_TOKEN: ${{ steps.app_token.outputs.token }} LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }} MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }} PORT_SOURCE_PR: ${{ github.event.pull_request.number }} run: | set -euo pipefail git config user.name "dms-ci[bot]" git config user.email "dms-ci[bot]@users.noreply.github.com" targets=$(jq -r '.[] | select(startswith("port ")) | sub("^port +"; "")' <<<"$LABELS" | sed -E 's,^stable-,,' | sort -u) [ -n "$targets" ] || { echo "no port labels, nothing to do"; exit 0; } [ -n "$MERGE_SHA" ] || { echo "::error::PR has no merge commit sha"; exit 1; } for ver in $targets; do echo "::group::port PR #${PORT_SOURCE_PR} ($MERGE_SHA) -> stable-$ver" bash scripts/port.sh "stable-$ver" "$MERGE_SHA" echo "::endgroup::" done