162 lines
5.9 KiB
YAML
162 lines
5.9 KiB
YAML
name: _release
|
||
|
||
#TODO test without these
|
||
permissions:
|
||
actions: read
|
||
contents: write
|
||
issues: write
|
||
pull-requests: write
|
||
|
||
concurrency:
|
||
group: release
|
||
cancel-in-progress: false
|
||
|
||
on:
|
||
workflow_call:
|
||
inputs:
|
||
force_release:
|
||
description: "Force release even if validation fails"
|
||
required: false
|
||
default: false
|
||
type: boolean
|
||
|
||
jobs:
|
||
validate-staging-build:
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
should_release: ${{ steps.validation.outputs.should-proceed }}
|
||
steps:
|
||
- name: Checkout staging
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
ref: staging
|
||
|
||
- name: Validate staging build status
|
||
id: validation
|
||
uses: ./.github/actions/validate-build-status
|
||
with:
|
||
job-name: trigger-staging-build / build
|
||
from-branch: staging
|
||
to-branch: main
|
||
force: ${{ inputs.force_release }}
|
||
|
||
generate-release-and-push-all:
|
||
needs: validate-staging-build
|
||
runs-on: ubuntu-latest
|
||
if: ${{ inputs.force_release == true || needs.validate-staging-build.outputs.should_release == 'true' }}
|
||
outputs:
|
||
skip-release: ${{steps.semantic-release.outputs.skip-release }}
|
||
steps:
|
||
- name: Checkout staging
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
ref: staging
|
||
|
||
- name: Setup Git SSH for commit signing and push operations
|
||
uses: ./.github/actions/setup-git-ssh
|
||
with:
|
||
commit-ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||
push-ssh-private-key: ${{ secrets.PUSH_SSH_PRIVATE_KEY }}
|
||
actor: ${{ github.actor }}
|
||
actor-id: ${{ github.actor_id }}
|
||
|
||
- name: Set git origin to GIT_ORIGIN_REPO_URL
|
||
run: |
|
||
GIT_ORIGIN_URL="${{ secrets.GIT_ORIGIN_REPO_URL }}"
|
||
if [ -n "$GIT_ORIGIN_URL" ]; then
|
||
git remote remove origin
|
||
if git remote add -f --tags origin "$GIT_ORIGIN_URL"; then
|
||
echo "✅ Git origin configured correctly"
|
||
else
|
||
echo "❌ Failed to configure Git origin"
|
||
echo "::error::Failed to configure Git origin"
|
||
exit 1
|
||
fi
|
||
else
|
||
echo "❌ No Git origin URL configured - cannot proceed without origin URL"
|
||
echo "::error::GIT_ORIGIN_REPO_URL secret is required but not configured"
|
||
exit 1
|
||
fi
|
||
- name: Merge staging commits to main
|
||
run: |
|
||
echo "🔄 Merging staging commits to main..."
|
||
git checkout main
|
||
|
||
STAGING_COMMITS=$(git log --oneline main..staging --pretty=format:"* %s")
|
||
|
||
if [ -z "$STAGING_COMMITS" ]; then
|
||
if [[ "${{inputs.force_release}}" == "true" ]]; then
|
||
echo "⚠️ No new commits in staging to merge, but force release is enabled"
|
||
echo "::warning::No commits to merge from staging to main"
|
||
exit 0
|
||
else
|
||
echo "❌ No new commits in staging to merge"
|
||
echo "::error::No commits to merge from staging to main"
|
||
exit 1
|
||
fi
|
||
else
|
||
echo "📋 Commits to be merged:"
|
||
echo "$STAGING_COMMITS"
|
||
|
||
if git merge staging -X theirs -m "chore: merge staging changes for next release"; then
|
||
echo "✅ Staging commits merged to main successfully"
|
||
else
|
||
echo "⚠️ Merge conflicts detected - resolving with staging preference..."
|
||
|
||
git checkout staging -- .
|
||
|
||
if [ -f CHANGELOG.md ]; then
|
||
git checkout HEAD -- CHANGELOG.md
|
||
echo "📋 Kept main's CHANGELOG.md (managed by semantic-release)"
|
||
fi
|
||
|
||
git add -A
|
||
git commit -m "chore: merge staging changes for next release"
|
||
echo "✅ Conflicts resolved - staging files preferred, main's CHANGELOG.md kept"
|
||
fi
|
||
fi
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version-file: ".nvmrc"
|
||
|
||
- name: Install semantic-release
|
||
run: npm install semantic-release
|
||
|
||
- name: Run semantic-release on main, generate release, and push
|
||
id: semantic-release
|
||
env:
|
||
GITHUB_TOKEN: "${{ github.token }}" # used for release generation
|
||
GIT_AUTHOR_NAME: "${{ github.actor }}"
|
||
GIT_AUTHOR_EMAIL: "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
|
||
GIT_COMMITTER_NAME: "${{ github.actor }}"
|
||
GIT_COMMITTER_EMAIL: "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
|
||
run: |
|
||
echo "🚀 Running semantic-release on main branch..."
|
||
npx semantic-release
|
||
|
||
if git log main -1 --format="%s" | grep -q "^chore: Release"; then
|
||
echo "✅ Semantic-release completed and pushed to origin/main"
|
||
echo "skip-release=false" >> $GITHUB_OUTPUT
|
||
else
|
||
echo "❌ Semantic-release did not generate a release, exiting."
|
||
echo "skip-release=true" >> $GITHUB_OUTPUT
|
||
[[ "${{ inputs.force_release }}" == "true" ]] && exit 1
|
||
fi
|
||
|
||
- name: Notify successful release
|
||
if: ${{ steps.semantic-release.outputs.skip-release != 'true' }}
|
||
run: |
|
||
echo "🎉 Production release completed successfully!"
|
||
echo "📋 Summary:"
|
||
echo " - Source: staging branch commits (regular merged)"
|
||
echo " - Target: main branch (semantic-release)"
|
||
echo " - Semantic-release: ✅ Complete on main"
|
||
echo " - staging branch: ℹ️ Maintains independent history"
|
||
echo " - dev branch: ℹ️ Maintains independent history"
|
||
echo " - Tags: ✅ Created and pushed"
|
||
echo " - GitHub & Git Origin: ✅ Main branch synchronized"
|
||
echo " - Status: 🚀 Ready to build and deploy!"
|