Release #53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Version number for this release" | |
| required: true | |
| dry_run: | |
| description: "Test workflow without publishing to CocoaPods" | |
| type: boolean | |
| default: false | |
| required: false | |
| publish_only: | |
| description: "Publish to CocoaPods without version updates or tagging" | |
| type: boolean | |
| default: false | |
| required: false | |
| jobs: | |
| release: | |
| runs-on: macos-15 | |
| outputs: | |
| commit_sha: ${{ steps.save_commit_info.outputs.commit_sha }} | |
| clean_commit_sha: ${{ steps.remove_unsafe_flags.outputs.clean_commit_sha }} | |
| version: ${{ github.event.inputs.version }} | |
| dry_run: ${{ github.event.inputs.dry_run }} | |
| tag_name: ${{ steps.create_tag.outputs.tag_name }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.2.2" | |
| - name: Install Ruby Gems | |
| run: sudo bundle install | |
| - name: Use Latest Stable Xcode | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: latest-stable | |
| - name: Ensure Platforms are Downloaded | |
| run: | | |
| xcodebuild -runFirstLaunch | |
| xcrun simctl list | |
| for platform in iOS watchOS tvOS visionOS; do | |
| echo "Downloading $platform platform..." | |
| xcodebuild -downloadPlatform $platform | |
| xcodebuild -runFirstLaunch | |
| done | |
| - name: Update version in podspec | |
| run: sed -i '' 's/s.version = "[^"]*"/s.version = "${{ github.event.inputs.version }}"/' KSCrash.podspec | |
| - name: Update version in source code | |
| run: | | |
| formatted_version_number=$(echo "${{ github.event.inputs.version }}" | awk -F. '{printf("%d.%02d%02d\n", $1, $2, $3)}') | |
| sed -i '' 's/const double KSCrashFrameworkVersionNumber = [^;]*/const double KSCrashFrameworkVersionNumber = '"$formatted_version_number"'/' Sources/KSCrashRecording/KSCrash.m | |
| sed -i '' 's/const unsigned char KSCrashFrameworkVersionString\[\] = "[^"]*"/const unsigned char KSCrashFrameworkVersionString[] = "${{ github.event.inputs.version }}"/' Sources/KSCrashRecording/KSCrash.m | |
| - name: Update README | |
| run: | | |
| # Update SPM version | |
| sed -i '' "s/\.package(url: \"https:\/\/github.com\/kstenerud\/KSCrash.git\", .upToNextMajor(from: \"[^\"]*\"))/\.package(url: \"https:\/\/github.com\/kstenerud\/KSCrash.git\", .upToNextMajor(from: \"${{ github.event.inputs.version }}\"))/" README.md | |
| # Update CocoaPods version | |
| VERSION="${{ github.event.inputs.version }}" | |
| if [[ "$VERSION" == *"-"* ]]; then | |
| # It's a pre-release version, use the full version | |
| sed -i '' "s/pod 'KSCrash'.*$/pod 'KSCrash', '~> $VERSION'/" README.md | |
| else | |
| # It's a release version, use major.minor | |
| sed -i '' "s/pod 'KSCrash'.*$/pod 'KSCrash', '~> ${VERSION%.*}'/" README.md | |
| fi | |
| echo "README.md updated with version ${{ github.event.inputs.version }}" | |
| - name: Commit version update | |
| id: commit_version | |
| if: ${{ github.event.inputs.publish_only != 'true' }} | |
| run: | | |
| git config --global user.name 'github-actions[bot]' | |
| git config --global user.email 'github-actions[bot]@users.noreply.github.com' | |
| git add . | |
| git commit -m "Update version to ${{ github.event.inputs.version }}" | |
| git push | |
| - name: Save commit information | |
| id: save_commit_info | |
| if: ${{ github.event.inputs.publish_only != 'true' }} | |
| run: | | |
| COMMIT_SHA=$(git rev-parse HEAD) | |
| echo "commit_sha=$COMMIT_SHA" >> $GITHUB_OUTPUT | |
| - name: Remove unsafe flags for release | |
| id: remove_unsafe_flags | |
| if: ${{ github.event.inputs.publish_only != 'true' }} | |
| run: | | |
| scripts/toggle-unsafe-flags.sh remove | |
| git add Package.swift | |
| git commit -m "Remove unsafe flags for release ${{ github.event.inputs.version }}" | |
| CLEAN_COMMIT_SHA=$(git rev-parse HEAD) | |
| echo "clean_commit_sha=$CLEAN_COMMIT_SHA" >> $GITHUB_OUTPUT | |
| git push | |
| - name: Create git tag | |
| id: create_tag | |
| if: ${{ github.event.inputs.publish_only != 'true' }} | |
| run: | | |
| if [[ "${{ github.event.inputs.dry_run }}" == "true" ]]; then | |
| TAG_NAME="${{ github.event.inputs.version }}-dryrun" | |
| else | |
| TAG_NAME="${{ github.event.inputs.version }}" | |
| fi | |
| git tag $TAG_NAME | |
| git push origin $TAG_NAME | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| - name: Revert unsafe flags removal | |
| if: ${{ github.event.inputs.publish_only != 'true' }} | |
| run: | | |
| git revert --no-edit ${{ steps.remove_unsafe_flags.outputs.clean_commit_sha }} | |
| git push | |
| - name: Publish to CocoaPods | |
| if: ${{ github.event.inputs.dry_run != 'true' }} | |
| env: | |
| COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_PASSWORD }} | |
| run: pod trunk push KSCrash.podspec --verbose | |
| rollback: | |
| runs-on: macos-15 | |
| needs: release | |
| if: failure() && github.event.inputs.publish_only != 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v2 | |
| with: | |
| fetch-depth: 0 | |
| - name: Fetch all tags | |
| run: | | |
| git fetch --tags | |
| - name: Delete git tag locally | |
| run: | | |
| # Use tag from outputs or construct it | |
| if [[ -n "${{ needs.release.outputs.tag_name }}" ]]; then | |
| TAG_TO_DELETE="${{ needs.release.outputs.tag_name }}" | |
| elif [[ "${{ needs.release.outputs.dry_run }}" == "true" ]]; then | |
| TAG_TO_DELETE="${{ needs.release.outputs.version }}-dryrun" | |
| else | |
| TAG_TO_DELETE="${{ needs.release.outputs.version }}" | |
| fi | |
| git tag -d $TAG_TO_DELETE || echo "Tag not found locally" | |
| echo "TAG_TO_DELETE=$TAG_TO_DELETE" >> $GITHUB_ENV | |
| - name: Delete git tag remotely | |
| run: | | |
| git push --delete origin ${{ env.TAG_TO_DELETE }} || echo "Tag not found on remote" | |
| - name: Pull latest changes | |
| run: | | |
| git pull origin "$(git branch --show-current)" | |
| - name: Check for commits to revert | |
| id: check_commits | |
| run: | | |
| echo "COMMITS_TO_REVERT=" >> $GITHUB_ENV | |
| # Check for the revert commit (that restored unsafe flags) | |
| REVERT_MSG="Revert \"Remove unsafe flags for release ${{ needs.release.outputs.version || github.event.inputs.version }}\"" | |
| REVERT_COMMIT=$(git log --format="%H" --grep="$REVERT_MSG" -n 1) | |
| if [[ -n "$REVERT_COMMIT" ]]; then | |
| echo "Found revert commit: $REVERT_COMMIT" | |
| echo "COMMITS_TO_REVERT=$REVERT_COMMIT" >> $GITHUB_ENV | |
| fi | |
| # Check for clean commit (unsafe flags removal) | |
| if [[ -n "${{ needs.release.outputs.clean_commit_sha }}" ]]; then | |
| echo "Clean commit found from outputs: ${{ needs.release.outputs.clean_commit_sha }}" | |
| if [[ -n "$COMMITS_TO_REVERT" ]]; then | |
| echo "COMMITS_TO_REVERT=$COMMITS_TO_REVERT ${{ needs.release.outputs.clean_commit_sha }}" >> $GITHUB_ENV | |
| else | |
| echo "COMMITS_TO_REVERT=${{ needs.release.outputs.clean_commit_sha }}" >> $GITHUB_ENV | |
| fi | |
| fi | |
| # Check for version commit | |
| if [[ -n "${{ needs.release.outputs.commit_sha }}" ]]; then | |
| echo "Version commit found from outputs: ${{ needs.release.outputs.commit_sha }}" | |
| if [[ -n "$COMMITS_TO_REVERT" ]]; then | |
| echo "COMMITS_TO_REVERT=$COMMITS_TO_REVERT ${{ needs.release.outputs.commit_sha }}" >> $GITHUB_ENV | |
| else | |
| echo "COMMITS_TO_REVERT=${{ needs.release.outputs.commit_sha }}" >> $GITHUB_ENV | |
| fi | |
| else | |
| # Fallback: search by commit message | |
| SEARCH_MSG="Update version to ${{ needs.release.outputs.version || github.event.inputs.version }}" | |
| FOUND_COMMIT=$(git log --format="%H" --grep="$SEARCH_MSG" -n 1) | |
| if [[ -n "$FOUND_COMMIT" ]]; then | |
| echo "Found version commit by message: $FOUND_COMMIT" | |
| if [[ -n "$COMMITS_TO_REVERT" ]]; then | |
| echo "COMMITS_TO_REVERT=$COMMITS_TO_REVERT $FOUND_COMMIT" >> $GITHUB_ENV | |
| else | |
| echo "COMMITS_TO_REVERT=$FOUND_COMMIT" >> $GITHUB_ENV | |
| fi | |
| fi | |
| fi | |
| if [[ -z "$COMMITS_TO_REVERT" ]]; then | |
| echo "No commits found to revert." | |
| echo "SHOULD_REVERT=false" >> $GITHUB_ENV | |
| else | |
| echo "SHOULD_REVERT=true" >> $GITHUB_ENV | |
| fi | |
| - name: Revert commits | |
| if: env.SHOULD_REVERT == 'true' | |
| run: | | |
| echo "Commits to revert: ${{ env.COMMITS_TO_REVERT }}" | |
| git log --oneline -n 5 | |
| git config --global user.name 'github-actions[bot]' | |
| git config --global user.email 'github-actions[bot]@users.noreply.github.com' | |
| # Revert commits in order (they're listed newest to oldest) | |
| for commit in ${{ env.COMMITS_TO_REVERT }}; do | |
| echo "Reverting commit $commit..." | |
| git revert --no-edit $commit | |
| done | |
| - name: Push reverts | |
| if: env.SHOULD_REVERT == 'true' | |
| run: | | |
| git push || { git status; exit 1; } |