mirror of
https://github.com/docker/cli.git
synced 2026-11-06 13:10:41 -04:00
158 lines
5.3 KiB
YAML
158 lines
5.3 KiB
YAML
name: Sync Docker release branch
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ inputs.release_branch }}
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
release_branch:
|
|
description: Release branch to sync, for example 29.x
|
|
required: true
|
|
type: string
|
|
tag:
|
|
description: Tag to sync from, for example v29.6.0
|
|
required: true
|
|
type: string
|
|
dry_run:
|
|
description: Merge but don't push
|
|
required: true
|
|
default: false
|
|
type: boolean
|
|
|
|
jobs:
|
|
sync-release-branch:
|
|
runs-on: ubuntu-26.04
|
|
permissions:
|
|
contents: write
|
|
actions: write
|
|
outputs:
|
|
base_sha: ${{ steps.sync.outputs.base_sha }}
|
|
has_changes: ${{ steps.sync.outputs.has_changes }}
|
|
temporary_branch: ${{ steps.sync.outputs.temporary_branch }}
|
|
temporary_sha: ${{ steps.sync.outputs.temporary_sha }}
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Validate
|
|
env:
|
|
BRANCH: ${{ github.ref_name }}
|
|
RELEASE_BRANCH: ${{ inputs.release_branch }}
|
|
run: |
|
|
if [ "$BRANCH" != "master" ]; then
|
|
echo "::error::This workflow is expected to be run on master, not $BRANCH"
|
|
exit 1
|
|
fi
|
|
if [ "$RELEASE_BRANCH" = "master" ]; then
|
|
echo "::error::The release branch must not be master"
|
|
exit 1
|
|
fi
|
|
if ! [[ "$RELEASE_BRANCH" =~ ^[0-9]+\.[x0-9]+$ ]]; then
|
|
echo "::error::Invalid release branch name: '$RELEASE_BRANCH'. Expected format: 29.x"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Configure git author
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
- name: Sync release branch to tag range
|
|
id: sync
|
|
env:
|
|
DRY_RUN: ${{ inputs.dry_run }}
|
|
RELEASE_BRANCH: ${{ inputs.release_branch }}
|
|
RUN_ATTEMPT: ${{ github.run_attempt }}
|
|
RUN_ID: ${{ github.run_id }}
|
|
TAG: ${{ inputs.tag }}
|
|
run: |
|
|
set -o pipefail
|
|
base_sha=$(git rev-parse "origin/$RELEASE_BRANCH")
|
|
temporary_branch="process/sync-release-branch/$RUN_ID-$RUN_ATTEMPT"
|
|
echo "base_sha=$base_sha" >> "$GITHUB_OUTPUT"
|
|
echo "temporary_branch=$temporary_branch" >> "$GITHUB_OUTPUT"
|
|
|
|
# Keep the master checkout unchanged so scripts run from the dispatched revision.
|
|
release_worktree="$RUNNER_TEMP/release-branch"
|
|
git worktree add --detach "$release_worktree" "$base_sha"
|
|
cd "$release_worktree"
|
|
|
|
tags_file=$(mktemp)
|
|
"$GITHUB_WORKSPACE/scripts/unmerged-tags" \
|
|
"origin/$RELEASE_BRANCH" \
|
|
"$TAG" \
|
|
> "$tags_file"
|
|
|
|
echo >> "$GITHUB_STEP_SUMMARY"
|
|
echo "## Tags to sync" >> "$GITHUB_STEP_SUMMARY"
|
|
echo >> "$GITHUB_STEP_SUMMARY"
|
|
sed 's/^/- /' "$tags_file" >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
xargs -r "$GITHUB_WORKSPACE/scripts/sync-branch" < "$tags_file" | tee -a "$GITHUB_STEP_SUMMARY"
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $(git rev-parse HEAD) == $(git rev-parse "origin/$RELEASE_BRANCH") ]]; then
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
echo "No changes to push"
|
|
exit 0
|
|
fi
|
|
|
|
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
|
git push origin "HEAD:refs/heads/$temporary_branch"
|
|
echo "temporary_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
|
|
|
push-release-branch:
|
|
needs: sync-release-branch
|
|
if: ${{ !inputs.dry_run && needs.sync-release-branch.outputs.has_changes == 'true' }}
|
|
runs-on: ubuntu-26.04
|
|
environment: docker-releases
|
|
permissions:
|
|
contents: write
|
|
actions: write
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Push release branch
|
|
env:
|
|
BASE_SHA: ${{ needs.sync-release-branch.outputs.base_sha }}
|
|
RELEASE_BRANCH: ${{ inputs.release_branch }}
|
|
TEMPORARY_BRANCH: ${{ needs.sync-release-branch.outputs.temporary_branch }}
|
|
TEMPORARY_SHA: ${{ needs.sync-release-branch.outputs.temporary_sha }}
|
|
run: |
|
|
git fetch origin "$RELEASE_BRANCH"
|
|
current_sha=$(git rev-parse "origin/$RELEASE_BRANCH")
|
|
if [[ "$current_sha" != "$BASE_SHA" ]]; then
|
|
echo "$RELEASE_BRANCH changed from $BASE_SHA to $current_sha"
|
|
exit 1
|
|
fi
|
|
|
|
git fetch origin "$TEMPORARY_BRANCH"
|
|
current_temporary_sha=$(git rev-parse FETCH_HEAD)
|
|
if [[ "$current_temporary_sha" != "$TEMPORARY_SHA" ]]; then
|
|
echo "$TEMPORARY_BRANCH changed from $TEMPORARY_SHA to $current_temporary_sha"
|
|
exit 1
|
|
fi
|
|
|
|
git push origin "FETCH_HEAD:$RELEASE_BRANCH"
|
|
|
|
- name: Delete temporary branch
|
|
env:
|
|
TEMPORARY_BRANCH: ${{ needs.sync-release-branch.outputs.temporary_branch }}
|
|
run: git push origin --delete "$TEMPORARY_BRANCH"
|