Skip to content

release publish: A6Gpm7Na #56

release publish: A6Gpm7Na

release publish: A6Gpm7Na #56

# This workflow publishes a release by creating a version tag.
# It is intended to be run with workflow_dispatch event by the automation.
on:
workflow_dispatch:
inputs:
release_handle:
description: 'Release handle JSON string containing release information'
required: true
type: string
workflow_uuid:
description: 'Optional UUID to identify this workflow run'
required: false
pr_to_official_library:
description: 'Open a PR to official library repo'
type: boolean
default: false
slack_channel_id:
description: 'Slack channel ID to duplicate links to announcement messages to'
required: false
type: string
default: ''
slack_thread_ts:
description: 'Thread timestamp to post message as a reply (optional)'
required: false
type: string
default: ''
env:
TARGET_OFFICIAL_IMAGES_REPO: docker-library/official-images
FORKED_OFFICIAL_IMAGES_REPO: redis-developer/docker-library-official-images
PR_USER_MENTIONS: "@yossigo @dagansandler @Peter-Sh @AngelYanev @dariaguy @kalinstaykov @hilabarkai @gonen-red"
# UUID is used to help automation to identify workflow run in the list of workflow runs.
run-name: "release publish${{ github.event.inputs.workflow_uuid && format(': {0}', github.event.inputs.workflow_uuid) || '' }}"
jobs:
publish-release:
runs-on: ["ubuntu-latest"]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Parse release handle and validate
id: parse-release
shell: bash
run: |
# Parse the JSON input
RELEASE_HANDLE='${{ github.event.inputs.release_handle }}'
echo "Parsing release handle JSON:"
echo "$RELEASE_HANDLE" | jq .
# Extract release_commit_sha
RELEASE_COMMIT_SHA=$(echo "$RELEASE_HANDLE" | jq -r '.release_commit_sha // empty')
# Validate that release_commit_sha exists and is not empty
if [ -z "$RELEASE_COMMIT_SHA" ] || [ "$RELEASE_COMMIT_SHA" = "null" ]; then
echo "Error: release_commit_sha is missing or empty in release_handle"
echo "Release handle content: $RELEASE_HANDLE"
exit 1
fi
# Extract release_version for tag creation
RELEASE_VERSION=$(echo "$RELEASE_HANDLE" | jq -r '.release_version // empty')
if [ -z "$RELEASE_VERSION" ] || [ "$RELEASE_VERSION" = "null" ]; then
echo "Error: release_version is missing or empty in release_handle"
echo "Release handle content: $RELEASE_HANDLE"
exit 1
fi
echo "Successfully parsed release handle:"
echo " release_commit_sha: $RELEASE_COMMIT_SHA"
echo " release_version: $RELEASE_VERSION"
# Set outputs for next steps
echo "release_commit_sha=$RELEASE_COMMIT_SHA" >> $GITHUB_OUTPUT
echo "release_version=$RELEASE_VERSION" >> $GITHUB_OUTPUT
- name: Create version tag
uses: redis-developer/redis-oss-release-automation/.github/actions/create-tag-verified@main
with:
tag: v${{ steps.parse-release.outputs.release_version }}
ref: ${{ steps.parse-release.outputs.release_commit_sha }}
gh_token: ${{ secrets.GITHUB_TOKEN }}
- name: Sync forked official-images repo
shell: bash
env:
GH_TOKEN: ${{ secrets.GH_TOKEN_FOR_PR_2 }}
run: |
echo "Syncing fork ${{ env.FORKED_OFFICIAL_IMAGES_REPO }} with upstream ${{ env.TARGET_OFFICIAL_IMAGES_REPO }}"
# Use GitHub API to sync the fork with upstream
# POST /repos/{owner}/{repo}/merge-upstream
response=$(curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GH_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/${{ env.FORKED_OFFICIAL_IMAGES_REPO }}/merge-upstream" \
-d '{"branch":"master"}')
echo "API Response:"
echo "$response" | jq '.'
# Check if sync was successful
if echo "$response" | jq -e '.message' > /dev/null 2>&1; then
message=$(echo "$response" | jq -r '.message')
if [ "$message" = "This branch is not behind the upstream docker-library:master" ]; then
echo "Fork is already up to date"
elif echo "$message" | grep -q "Successfully fetched and fast-forwarded"; then
echo "Successfully synced fork with upstream"
else
echo "Warning: Unexpected response message: $message"
fi
elif echo "$response" | jq -e '.merge_type' > /dev/null 2>&1; then
merge_type=$(echo "$response" | jq -r '.merge_type')
echo "Successfully synced fork (merge type: $merge_type)"
else
echo "Error: Failed to sync fork"
echo "$response"
exit 1
fi
- name: Checkout official-images repo
uses: actions/checkout@v4
with:
path: official-images
repository: ${{ github.event.inputs.pr_to_official_library == 'true' && env.TARGET_OFFICIAL_IMAGES_REPO || env.FORKED_OFFICIAL_IMAGES_REPO }}
- name: Install release automation dependencies
uses: ./.github/actions/release-automation-install
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Apply Docker image tags to multi-arch images
if: ${{ !contains(steps.parse-release.outputs.release_version, '-') }}
shell: bash
run: |
REGISTRY=$(echo "ghcr.io/${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
RELEASE_VERSION="${{ steps.parse-release.outputs.release_version }}"
for DISTRIBUTION in debian alpine; do
SOURCE_TAG="${REGISTRY}:${RELEASE_VERSION}-${DISTRIBUTION}"
echo "Processing ${SOURCE_TAG}"
TAGS=$(uv --directory release-automation run release-automation \
generate-image-tags "${RELEASE_VERSION}" "${DISTRIBUTION}" 2>/dev/null)
if [ -z "$TAGS" ]; then
echo "No tags generated for ${RELEASE_VERSION} ${DISTRIBUTION}, skipping"
continue
fi
echo "Generated tags: ${TAGS}"
IFS=',' read -ra TAG_ARRAY <<< "$TAGS"
TAG_ARGS=""
for tag in "${TAG_ARRAY[@]}"; do
tag=$(echo "$tag" | xargs)
TAG_ARGS="${TAG_ARGS} -t ${REGISTRY}:${tag}"
done
docker buildx imagetools create ${TAG_ARGS} "${SOURCE_TAG}"
done
- name: Generate stackbrew library content
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Extract major version from release version (e.g., "8.2.1" -> "8")
MAJOR_VERSION=$(uv --directory release-automation run release-automation redis-version major "${{ steps.parse-release.outputs.release_version }}")
echo "Major version: $MAJOR_VERSION"
# Generate updated stackbrew content using uv
uv --directory release-automation run release-automation update-stackbrew-file $MAJOR_VERSION --input ../official-images/library/redis --output ../official-images/library/redis
cd official-images && git diff --color
cd -
- name: Create pull request to official-images
id: create-pr
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GH_TOKEN_FOR_PR_2 }}
draft: true
push-to-fork: ${{ github.event.inputs.pr_to_official_library == 'true' && env.FORKED_OFFICIAL_IMAGES_REPO || '' }}
path: official-images
branch: redis-${{ steps.parse-release.outputs.release_version }}
commit-message: "Redis: Update to ${{ steps.parse-release.outputs.release_version }}"
title: "Redis: Update to ${{ steps.parse-release.outputs.release_version }}"
body: |
Automated update for Redis ${{ steps.parse-release.outputs.release_version }}
Release commit: ${{ steps.parse-release.outputs.release_commit_sha }}
Release tag: v${{ steps.parse-release.outputs.release_version }}
Compare: ${{ github.server_url }}/${{ github.repository }}/compare/v${{ steps.parse-release.outputs.release_version }}^1...v${{ steps.parse-release.outputs.release_version }}
${{ env.PR_USER_MENTIONS }}
- name: Validate PR creation
env:
PULL_REQUEST_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }}
shell: bash
run: |
if [ -z "$PULL_REQUEST_NUMBER" ]; then
echo "::error::Failed to create PR, pull-request-number is empty"
exit 1
fi
# Since publish is only for public releases, always send notifications to the announcement channel first
- name: Send Success Slack notification
id: slack-success
continue-on-error: true
uses: ./.github/actions/slack-notification
with:
slack_func: slack_format_docker_PR_message
slack_channel_id: ${{ vars.SLACK_CHANNEL_ID }}
release_tag: v${{ steps.parse-release.outputs.release_version }}
pr_url: ${{ steps.create-pr.outputs.pull-request-url }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
# Post link to message in the announcement channel to the slack thread if requested
# This makes user to see the link to the "official" message if he started the release in the thread
- name: Post announcement link to Slack
continue-on-error: true
if: |
github.event.inputs.slack_channel_id != '' &&
steps.slack-success.outputs.slack_url != ''
uses: ./.github/actions/slack-notification
with:
slack_func: slack_format_simple_msg
slack_channel_id: ${{ github.event.inputs.slack_channel_id }}
slack_thread_ts: ${{ github.event.inputs.slack_thread_ts }}
message: ${{ steps.slack-success.outputs.slack_url }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- name: Create Release info
id: create-release-info
shell: bash
run: |
# Create release_info.json with all fields, then filter out empty ones
jq -n \
--arg release_version "${{ steps.parse-release.outputs.release_version }}" \
--arg pull_request_number "${{ steps.create-pr.outputs.pull-request-number }}" \
--arg pull_request_url "${{ steps.create-pr.outputs.pull-request-url }}" \
--argjson run_id "${{ github.run_id }}" \
--arg slack_ts "${{ steps.slack-success.outputs.slack_ts }}" \
--arg slack_channel_id "${{ github.event.inputs.slack_channel_id || vars.SLACK_CHANNEL_ID }}" \
--arg slack_message_url "${{ steps.slack-success.outputs.slack_url }}" \
'{
release_version: $release_version,
pull_request_number: $pull_request_number,
pull_request_url: $pull_request_url,
run_id: $run_id,
slack_ts: $slack_ts,
slack_channel_id: $slack_channel_id,
slack_message_url: $slack_message_url
} | with_entries(select(.value != ""))' > result.json
echo "Created result.json for release_info:"
cat result.json | jq '.'
- name: Upload release info artifact
uses: actions/upload-artifact@v4
with:
name: release_info
path: result.json
retention-days: 400
- name: Send Failure Slack notification
id: slack-failure
if: failure()
uses: ./.github/actions/slack-notification
with:
slack_func: slack_format_failure_message
slack_channel_id: ${{ vars.SLACK_CHANNEL_ID }}
release_tag: v${{ steps.parse-release.outputs.release_version }}
message: "Docker PR failed"
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
# Post link to message in the announcement channel to the slack thread if requested
# This makes user to see the link to the "official" message if he started the release in the thread
- name: Post failure notification link to Slack
continue-on-error: true
if: |
failure() &&
github.event.inputs.slack_channel_id != '' &&
steps.slack-failure.outputs.slack_url != ''
uses: ./.github/actions/slack-notification
with:
slack_func: slack_format_simple_msg
slack_channel_id: ${{ github.event.inputs.slack_channel_id }}
slack_thread_ts: ${{ github.event.inputs.slack_thread_ts }}
message: ${{ steps.slack-failure.outputs.slack_url }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}