mirror of
https://github.com/we-promise/sure.git
synced 2026-07-12 21:05:20 +00:00
* Fix prerelease version bump workflow
* Fix prerelease version-bump job: add PR fallback for protected branches
### Motivation
- The prerelease version bump job was failing when it could not push to protected release branches, causing the workflow to error instead of progressing.
- The job needs permission and robust push logic so prerelease automation can update `.sure-version` and `charts/sure/Chart.yaml` even when direct pushes are blocked.
### Description
- Grant the `bump-pre_release-version` job `pull-requests: write` permission so it may open an automated PR when direct pushes are disallowed.
- Harden the bump step: enable `set -euo pipefail`, pass `GH_TOKEN` into the job environment, and use fully-qualified branch refs for pushes.
- Add retry + rebase logic for direct pushes and a fallback path that pushes the changes to an `automation/bump-version-after-...` branch and opens a PR with `gh pr create` when direct push attempts fail.
- Preserve existing validations that ensure `.sure-version` and `charts/sure/Chart.yaml` exist and the prerelease portion is parsed before writing the bump.
### Testing
- Verified workflow YAML parses with `ruby -e 'require "yaml"; YAML.load_file(".github/workflows/publish.yml"); puts "YAML OK"'` and it succeeded.
- Confirmed the bump job has the expected permission with `ruby -e 'require "yaml"; workflow=YAML.load_file(".github/workflows/publish.yml"); abort("missing bump job") unless workflow.dig("jobs", "bump-pre_release-version", "permissions", "pull-requests") == "write"; puts "bump permissions OK"'` and it succeeded.
- Ran ActionLint via `go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.8 .github/workflows/publish.yml` and received no actionable errors.
- Ran `git diff --check` to ensure no whitespace/format issues and it succeeded.
* Harden pre-release bump job: validation, retries and PR fallback
### Motivation
- Make the `bump-pre_release-version` job more robust by validating prerelease version formats and failing early on unexpected inputs.
- Handle protected branches gracefully by attempting direct pushes with retries and falling back to creating a pull request when direct push is blocked.
- Ensure the workflow has the permissions required to open PRs when needed.
### Description
- Added `pull-requests: write` to the job `permissions` so the workflow can create PRs when required.
- Hardened the bump script with `set -euo pipefail` and a strict regex that validates and extracts `BASE_VERSION`, prerelease tag, and number using `BASH_REMATCH` before incrementing the prerelease counter.
- Simplified and made file reads safer by using input redirection for `tr` and improved error messages for missing or malformed version files.
- Reworked commit/push logic to set a commit message variable, attempt direct pushes with exponential backoff and detection of branch-protection errors, and when rejected create a dedicated bump branch and open a PR via `gh pr create`.
### Testing
- Validated the modified workflow YAML with a YAML linter; no syntax errors were reported.
- Executed the updated bump logic in a CI dry-run (workflow syntax validation on GitHub Actions) and the workflow file was accepted by the Actions syntax checks.
* Add manual workflow triggers and robust pre-release bump with protected-branch fallback
### Motivation
- Allow manual invocation of PR and chart CI workflows via `workflow_dispatch` for on-demand runs.
- Make the pre-release version bump process more robust and reliable when `refs/tags/v*` releases are published.
- Ensure the bump can proceed even when the target branch is protected by creating an automated pull request and running PR checks.
### Description
- Added `workflow_dispatch` to `.github/workflows/pr.yml` and `.github/workflows/chart-ci.yml` to support manual runs.
- Extended `bump-pre_release-version` job in `.github/workflows/publish.yml` to request `actions: write` and `pull-requests: write` permissions.
- Rewrote the bump script to use `set -euo pipefail` and a single regex validation to parse and increment prerelease versions (e.g. `1.2.3-alpha.4`), update `.sure-version`, and update `charts/sure/Chart.yaml` reliably.
- Improved commit and push flow by adding `GH_TOKEN`, using a consistent commit message variable, attempting direct pushes with retry and rebase, detecting branch-protection failures, and falling back to creating a bumped branch and an automated PR via `gh pr create`; the workflow also dispatches `pr.yml` and `chart-ci.yml` runs for the created branch.
### Testing
- No automated tests were run as part of this change; behavior will be exercised when the workflow creates a bump PR or when workflows are manually triggered via the new `workflow_dispatch` events.
579 lines
21 KiB
YAML
579 lines
21 KiB
YAML
# Reference: https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
|
|
|
|
# Conditions for pushing the image to GHCR:
|
|
# - Triggered by push to default branch (`main`)
|
|
# - Triggered by push to a version tag (`v*`)
|
|
# - Triggered by a scheduled run
|
|
# - Triggered manually via `workflow_dispatch` with `push: true`
|
|
#
|
|
# Conditional expression:
|
|
# github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push
|
|
|
|
name: Publish Docker image
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
ref:
|
|
description: 'Git ref (tag or commit SHA) to build'
|
|
required: true
|
|
type: string
|
|
default: 'main'
|
|
push:
|
|
description: 'Push the image to container registry'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
branches:
|
|
- main
|
|
paths-ignore:
|
|
- 'charts/**'
|
|
- 'mobile/**'
|
|
schedule:
|
|
- cron: '30 1 * * *'
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
IMAGE_NAME: ${{ github.repository }}
|
|
|
|
permissions:
|
|
contents: write
|
|
packages: write
|
|
|
|
jobs:
|
|
ci:
|
|
uses: ./.github/workflows/ci.yml
|
|
|
|
build:
|
|
name: Build Docker image
|
|
needs: [ ci ]
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
platform: [amd64, arm64]
|
|
include:
|
|
- platform: amd64
|
|
runs-on: ubuntu-24.04
|
|
- platform: arm64
|
|
runs-on: ubuntu-24.04-arm
|
|
|
|
timeout-minutes: 60
|
|
runs-on: ${{ matrix.runs-on }}
|
|
|
|
outputs:
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
|
|
steps:
|
|
- name: Check out the repo
|
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
|
with:
|
|
persist-credentials: false
|
|
ref: ${{ github.event.inputs.ref || github.ref }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
|
|
|
- name: Log in to the container registry
|
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Configure image tags
|
|
id: tag_config
|
|
shell: bash
|
|
run: |
|
|
BASE_CONFIG="type=sha,format=long"
|
|
if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then
|
|
BASE_CONFIG+=$'\n'"type=schedule,pattern=nightly"
|
|
BASE_CONFIG+=$'\n'"type=schedule,pattern=nightly-{{date 'ddd'}}"
|
|
elif [[ "$GITHUB_REF" == refs/tags/* ]]; then
|
|
TAG_NAME="${GITHUB_REF#refs/tags/}"
|
|
if [[ "$TAG_NAME" == v* ]]; then
|
|
BASE_CONFIG="type=semver,pattern={{version}}"
|
|
if [[ "$TAG_NAME" == v*-alpha* ]]; then
|
|
BASE_CONFIG+=$'\n'"type=raw,value=latest"
|
|
else
|
|
BASE_CONFIG+=$'\n'"type=raw,value=stable"
|
|
fi
|
|
fi
|
|
fi
|
|
{
|
|
echo 'TAGS_SPEC<<EOF'
|
|
echo "$BASE_CONFIG"
|
|
echo EOF
|
|
} >> $GITHUB_ENV
|
|
|
|
- name: Get current date (RFC 3339 format)
|
|
id: date
|
|
run: echo "date=$(date -Iseconds)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Extract metadata for Docker
|
|
id: meta
|
|
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
flavor: latest=false
|
|
tags: ${{ env.TAGS_SPEC }}
|
|
labels: |
|
|
org.opencontainers.image.version=${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || '' }}
|
|
org.opencontainers.image.created=${{ steps.date.outputs.date }}
|
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
|
org.opencontainers.image.vendor=we-promise
|
|
org.opencontainers.image.title=Sure
|
|
org.opencontainers.image.description=A multi-arch Docker image for the Sure Rails app
|
|
|
|
- name: Publish 'linux/${{ matrix.platform }}' image by digest
|
|
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
|
id: build
|
|
with:
|
|
context: .
|
|
build-args: BUILD_COMMIT_SHA=${{ github.sha }}
|
|
platforms: 'linux/${{ matrix.platform }}'
|
|
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache-${{ matrix.platform }}
|
|
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache-${{ matrix.platform }},mode=max
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
provenance: false
|
|
push: true
|
|
# DO NOT REMOVE `oci-mediatypes=true`, fixes annotation not showing up on job.merge.steps[-1]
|
|
# ref: https://github.com/docker/build-push-action/discussions/1022
|
|
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},name-canonical=true,push-by-digest=true,oci-mediatypes=true
|
|
|
|
- name: Export the Docker image digest
|
|
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
|
|
run: |
|
|
mkdir -p "${RUNNER_TEMP}"/digests
|
|
echo "${DIGEST#sha256:}" > "${RUNNER_TEMP}/digests/digest-${PLATFORM}"
|
|
env:
|
|
DIGEST: ${{ steps.build.outputs.digest }}
|
|
PLATFORM: ${{ matrix.platform }}
|
|
|
|
- name: Upload the Docker image digest
|
|
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
|
|
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
with:
|
|
name: digest-${{ matrix.platform }}
|
|
path: ${{ runner.temp }}/digests/*
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
merge:
|
|
name: Merge multi-arch manifest & push multi-arch tag
|
|
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
|
|
needs: [build]
|
|
|
|
timeout-minutes: 60
|
|
runs-on: 'ubuntu-24.04'
|
|
|
|
permissions:
|
|
packages: write
|
|
|
|
steps:
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
|
|
|
- name: Download Docker image digests
|
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
|
with:
|
|
path: ${{ runner.temp }}/digests
|
|
pattern: digest-*
|
|
merge-multiple: true
|
|
|
|
- name: Log in to the container registry
|
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Merge and push Docker image
|
|
env:
|
|
TAGS: ${{ needs.build.outputs.tags }}
|
|
DIGESTS_DIR: ${{ runner.temp }}/digests
|
|
REF_NAME: ${{ github.ref_name }}
|
|
shell: bash -xeuo pipefail {0}
|
|
run: |
|
|
tag_args=()
|
|
while IFS=$'\n' read -r tag; do
|
|
[[ -n "${tag}" ]] || continue
|
|
tag_args+=("--tag=${tag}")
|
|
done <<< "${TAGS}"
|
|
|
|
image_args=()
|
|
for PLATFORM in amd64 arm64; do
|
|
image_args+=("${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:$(<"${DIGESTS_DIR}/digest-${PLATFORM}")")
|
|
done
|
|
|
|
annotations=(
|
|
"index:org.opencontainers.image.created=$(date -Iseconds)"
|
|
'index:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}'
|
|
'index:org.opencontainers.image.revision=${{ github.sha }}'
|
|
"index:org.opencontainers.image.ref.name=${REF_NAME}"
|
|
'index:org.opencontainers.image.vendor=we-promise'
|
|
'index:org.opencontainers.image.licenses=AGPL-3.0'
|
|
'index:org.opencontainers.image.title=Sure'
|
|
'index:org.opencontainers.image.description=A multi-arch Docker image for the Sure Rails app'
|
|
)
|
|
annotation_args=()
|
|
for annotation in "${annotations[@]}"; do
|
|
annotation_args+=("--annotation=${annotation}")
|
|
done
|
|
if [[ $GITHUB_REF_TYPE == "tag" ]]; then
|
|
annotation_args+=("--annotation=index:org.opencontainers.image.version=$GITHUB_REF_NAME")
|
|
fi
|
|
|
|
attempts=0
|
|
until docker buildx imagetools create \
|
|
"${annotation_args[@]}" \
|
|
"${tag_args[@]}" \
|
|
"${image_args[@]}" \
|
|
; do
|
|
attempts=$((attempts + 1))
|
|
if [[ $attempts -ge 3 ]]; then
|
|
echo "[$(date -u)] ERROR: Failed after 3 attempts." >&2
|
|
exit 1
|
|
fi
|
|
delay=$((2 ** attempts))
|
|
if [[ $delay -gt 15 ]]; then delay=15; fi
|
|
echo "Push failed (attempt $attempts). Retrying in ${delay} seconds..."
|
|
sleep ${delay}
|
|
done
|
|
|
|
|
|
helm:
|
|
name: Package Helm chart
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
uses: ./.github/workflows/helm-publish.yml
|
|
with:
|
|
chart_version: ${{ github.ref_name }}
|
|
app_version: ${{ github.ref_name }}
|
|
update_gh_pages: true
|
|
secrets: inherit
|
|
|
|
mobile:
|
|
name: Build Mobile Apps
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
uses: ./.github/workflows/flutter-build.yml
|
|
secrets: inherit
|
|
|
|
release:
|
|
name: Create GitHub Release
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
needs: [merge, mobile, helm]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
steps:
|
|
- name: Download Android APK artifact
|
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
|
with:
|
|
name: app-release-apk
|
|
path: ${{ runner.temp }}/mobile-artifacts
|
|
|
|
- name: Download iOS build artifact
|
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
|
with:
|
|
name: ios-build-unsigned
|
|
path: ${{ runner.temp }}/ios-build
|
|
|
|
- name: Download Helm chart artifact
|
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
|
with:
|
|
name: helm-chart-package
|
|
path: ${{ runner.temp }}/helm-artifacts
|
|
|
|
- name: Prepare release assets
|
|
env:
|
|
REF_NAME: ${{ github.ref_name }}
|
|
run: |
|
|
mkdir -p ${{ runner.temp }}/release-assets
|
|
|
|
echo "=== Debugging: List downloaded artifacts ==="
|
|
echo "Mobile artifacts:"
|
|
ls -laR "${{ runner.temp }}/mobile-artifacts" || echo "No mobile-artifacts directory"
|
|
echo "iOS build:"
|
|
ls -laR "${{ runner.temp }}/ios-build" || echo "No ios-build directory"
|
|
echo "==========================================="
|
|
|
|
# Copy debug APK if it exists
|
|
if [ -f "${{ runner.temp }}/mobile-artifacts/app-debug.apk" ]; then
|
|
cp "${{ runner.temp }}/mobile-artifacts/app-debug.apk" "${{ runner.temp }}/release-assets/sure-${REF_NAME}-debug.apk"
|
|
echo "✓ Debug APK prepared"
|
|
fi
|
|
|
|
# Copy release APK if it exists
|
|
if [ -f "${{ runner.temp }}/mobile-artifacts/app-release.apk" ]; then
|
|
cp "${{ runner.temp }}/mobile-artifacts/app-release.apk" "${{ runner.temp }}/release-assets/sure-${REF_NAME}.apk"
|
|
echo "✓ Release APK prepared"
|
|
fi
|
|
|
|
# Create iOS app archive (zip the .app bundle)
|
|
# Path preserves directory structure from artifact upload
|
|
if [ -d "${{ runner.temp }}/ios-build/ios/iphoneos/Runner.app" ]; then
|
|
cd "${{ runner.temp }}/ios-build/ios/iphoneos"
|
|
zip -r "${{ runner.temp }}/release-assets/sure-${REF_NAME}-ios-unsigned.zip" Runner.app
|
|
echo "✓ iOS build archive prepared"
|
|
fi
|
|
|
|
# Copy iOS build info
|
|
if [ -f "${{ runner.temp }}/ios-build/ios-build-info.txt" ]; then
|
|
cp "${{ runner.temp }}/ios-build/ios-build-info.txt" "${{ runner.temp }}/release-assets/"
|
|
fi
|
|
|
|
# Copy Helm chart package(s)
|
|
if compgen -G "${{ runner.temp }}/helm-artifacts/*.tgz" > /dev/null; then
|
|
cp ${{ runner.temp }}/helm-artifacts/*.tgz "${{ runner.temp }}/release-assets/"
|
|
echo "✓ Helm chart package prepared"
|
|
fi
|
|
|
|
echo "Release assets:"
|
|
ls -la "${{ runner.temp }}/release-assets/"
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
|
with:
|
|
tag_name: ${{ github.ref_name }}
|
|
name: ${{ github.ref_name }}
|
|
draft: false
|
|
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
|
|
generate_release_notes: true
|
|
files: |
|
|
${{ runner.temp }}/release-assets/*
|
|
body: |
|
|
## Mobile Debug Builds
|
|
|
|
This release includes debug builds of the mobile applications. Download from the `Assets` area below.
|
|
|
|
- **Android APK**: Debug build for testing on Android devices
|
|
- **iOS Build**: Unsigned iOS build (requires code signing for installation)
|
|
|
|
> **Note**: These are debug builds intended for testing purposes. For production use, please build from source with proper signing credentials.
|
|
|
|
|
|
create_release_branch:
|
|
name: Create or update release branch
|
|
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, 'alpha') && !contains(github.ref_name, 'beta') && !contains(github.ref_name, 'rc')
|
|
needs: [release]
|
|
runs-on: ubuntu-latest
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
steps:
|
|
- name: Create/update minor release branch
|
|
env:
|
|
TAG_NAME: ${{ github.ref_name }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
BRANCH_NAME="$(echo "$TAG_NAME" | sed -E 's/^v([0-9]+)\.([0-9]+)\..*/v\1.\2-release-branch/')"
|
|
SHA="${GITHUB_SHA}"
|
|
|
|
echo "Updating ${BRANCH_NAME} -> ${SHA}"
|
|
if ! gh api "repos/${GITHUB_REPOSITORY}/git/refs/heads/${BRANCH_NAME}" \
|
|
--method PATCH \
|
|
--field sha="${SHA}" \
|
|
--field force=true 2>/dev/null; then
|
|
gh api "repos/${GITHUB_REPOSITORY}/git/refs" \
|
|
--method POST \
|
|
--field ref="refs/heads/${BRANCH_NAME}" \
|
|
--field sha="${SHA}"
|
|
fi
|
|
|
|
bump-pre_release-version:
|
|
name: Bump Pre-release Version
|
|
if: startsWith(github.ref, 'refs/tags/v') && (contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc'))
|
|
needs: [merge]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
|
|
permissions:
|
|
actions: write
|
|
contents: write
|
|
pull-requests: write
|
|
|
|
steps:
|
|
- name: Determine source branch for tag
|
|
id: source_branch
|
|
run: |
|
|
# Fetch all branches to find which one contains this tag's commit
|
|
git init --quiet
|
|
git remote add origin "https://github.com/${{ github.repository }}.git"
|
|
git fetch origin --quiet
|
|
|
|
# Find branches containing the tagged commit
|
|
BRANCHES=$(git branch -r --contains ${{ github.sha }} | grep -v HEAD | sed 's/origin\///' | xargs)
|
|
echo "Branches containing commit: $BRANCHES"
|
|
|
|
# Prefer non-main branches (release branches) over main
|
|
SOURCE_BRANCH="main"
|
|
for branch in $BRANCHES; do
|
|
if [ "$branch" != "main" ] && [ "$branch" != "master" ]; then
|
|
SOURCE_BRANCH="$branch"
|
|
break
|
|
fi
|
|
done
|
|
|
|
echo "Selected source branch: $SOURCE_BRANCH"
|
|
echo "branch=$SOURCE_BRANCH" >> $GITHUB_OUTPUT
|
|
|
|
- name: Check out source branch
|
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
|
with:
|
|
ref: ${{ steps.source_branch.outputs.branch }}
|
|
token: ${{ github.token }}
|
|
|
|
- name: Bump pre-release version
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
VERSION_FILE=".sure-version"
|
|
CHART_FILE="charts/sure/Chart.yaml"
|
|
|
|
# Ensure version file exists
|
|
if [ ! -f "$VERSION_FILE" ]; then
|
|
echo "ERROR: Version file not found: $VERSION_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# Ensure chart file exists
|
|
if [ ! -f "$CHART_FILE" ]; then
|
|
echo "ERROR: Chart file not found: $CHART_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# Extract current version
|
|
CURRENT_VERSION=$(tr -d '[:space:]' < "$VERSION_FILE")
|
|
if [ -z "$CURRENT_VERSION" ]; then
|
|
echo "ERROR: Could not extract version from $VERSION_FILE"
|
|
exit 1
|
|
fi
|
|
echo "Current version: $CURRENT_VERSION"
|
|
|
|
if [[ ! "$CURRENT_VERSION" =~ ^([0-9]+\.[0-9]+\.[0-9]+)-(alpha|beta|rc)\.([0-9]+)$ ]]; then
|
|
echo "ERROR: Expected prerelease version like 1.2.3-alpha.4, got $CURRENT_VERSION"
|
|
exit 1
|
|
fi
|
|
|
|
BASE_VERSION="${BASH_REMATCH[1]}"
|
|
PRE_RELEASE_TAG="${BASH_REMATCH[2]}"
|
|
PRE_RELEASE_NUM="${BASH_REMATCH[3]}"
|
|
NEW_PRE_RELEASE_NUM=$((PRE_RELEASE_NUM + 1))
|
|
NEW_VERSION="${BASE_VERSION}-${PRE_RELEASE_TAG}.${NEW_PRE_RELEASE_NUM}"
|
|
echo "New version: $NEW_VERSION"
|
|
|
|
# Update the version file
|
|
echo "$NEW_VERSION" > "$VERSION_FILE"
|
|
|
|
# Verify the change
|
|
echo "Updated .sure-version:"
|
|
cat "$VERSION_FILE"
|
|
|
|
# Update Helm chart version and appVersion
|
|
sed -i -E "s/^version: .*/version: ${NEW_VERSION}/" "$CHART_FILE"
|
|
sed -i -E "s/^appVersion: .*/appVersion: \"${NEW_VERSION}\"/" "$CHART_FILE"
|
|
|
|
# Verify the change
|
|
echo "Updated Chart.yaml:"
|
|
grep -E "^(version|appVersion):" "$CHART_FILE"
|
|
|
|
- name: Commit and push version bump
|
|
env:
|
|
SOURCE_BRANCH: ${{ steps.source_branch.outputs.branch }}
|
|
GH_TOKEN: ${{ github.token }}
|
|
REF_NAME: ${{ github.ref_name }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
git add .sure-version
|
|
git add charts/sure/Chart.yaml
|
|
|
|
# Check if there are changes to commit
|
|
if git diff --cached --quiet; then
|
|
echo "No changes to commit - version may have already been bumped"
|
|
exit 0
|
|
fi
|
|
|
|
COMMIT_MESSAGE="Bump version to next iteration after ${REF_NAME} release"
|
|
git commit -m "$COMMIT_MESSAGE"
|
|
|
|
echo "Pushing to branch: $SOURCE_BRANCH"
|
|
|
|
# Push directly when allowed. Main is protected and must be updated
|
|
# through a pull request. Other branches get a direct-push attempt, but
|
|
# protected-branch rejections fall back to a pull request immediately.
|
|
push_succeeded=false
|
|
if [[ "$SOURCE_BRANCH" == "main" || "$SOURCE_BRANCH" == "master" ]]; then
|
|
echo "$SOURCE_BRANCH is protected; creating a pull request instead of pushing directly."
|
|
else
|
|
direct_push_output=""
|
|
for attempt in 1 2 3 4; do
|
|
set +e
|
|
direct_push_output=$(git push origin HEAD:"refs/heads/${SOURCE_BRANCH}" 2>&1)
|
|
push_status=$?
|
|
set -e
|
|
|
|
echo "$direct_push_output"
|
|
|
|
if [[ $push_status -eq 0 ]]; then
|
|
push_succeeded=true
|
|
break
|
|
fi
|
|
|
|
if grep -Eq 'GH006|Protected branch update failed|Changes must be made through a pull request' <<< "$direct_push_output"; then
|
|
echo "Direct push is blocked by branch protection; creating a pull request instead."
|
|
break
|
|
fi
|
|
|
|
if [[ $attempt -eq 4 ]]; then
|
|
echo "Direct push failed after 4 attempts; creating a pull request instead."
|
|
break
|
|
fi
|
|
|
|
delay=$((2 ** attempt))
|
|
echo "Push failed (attempt $attempt). Retrying in ${delay} seconds..."
|
|
sleep "$delay"
|
|
git fetch origin "${SOURCE_BRANCH}"
|
|
git rebase "origin/${SOURCE_BRANCH}"
|
|
done
|
|
fi
|
|
|
|
if [[ "$push_succeeded" == "true" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
SAFE_TAG=$(printf '%s' "${REF_NAME}" | tr -c '[:alnum:]._-' '-')
|
|
BUMP_BRANCH="automation/bump-version-after-${SAFE_TAG}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
|
|
|
|
git push --force-with-lease origin HEAD:"refs/heads/${BUMP_BRANCH}"
|
|
|
|
PR_BODY="This automated PR bumps .sure-version and charts/sure/Chart.yaml after the ${REF_NAME} pre-release. It was opened because the workflow could not push directly to ${SOURCE_BRANCH}."
|
|
|
|
PR_URL=$(gh pr create \
|
|
--repo "$GITHUB_REPOSITORY" \
|
|
--head "$BUMP_BRANCH" \
|
|
--base "$SOURCE_BRANCH" \
|
|
--title "$COMMIT_MESSAGE" \
|
|
--body "$PR_BODY")
|
|
|
|
echo "Created version bump PR: $PR_URL"
|
|
echo "Dispatching PR checks for $BUMP_BRANCH"
|
|
gh workflow run pr.yml --repo "$GITHUB_REPOSITORY" --ref "$BUMP_BRANCH"
|
|
gh workflow run chart-ci.yml --repo "$GITHUB_REPOSITORY" --ref "$BUMP_BRANCH"
|