From 506b0329699e1fa7bd436e7e2b726f65f4fafef0 Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:44:37 -0400 Subject: [PATCH 1/4] chore: Adding worflows for automated releases --- .github/workflows/release_authenticator.yml | 57 ++++++++++++++++++ .github/workflows/release_kickoff.yml | 18 ++++++ .github/workflows/unit_tests.yml | 11 ++++ Gemfile | 8 +++ fastlane/.gitignore | 1 + fastlane/Fastfile | 64 +++++++++++++++++++++ fastlane/Pluginfile | 5 ++ fastlane/README.md | 24 ++++++++ 8 files changed, 188 insertions(+) create mode 100644 .github/workflows/release_authenticator.yml create mode 100644 .github/workflows/release_kickoff.yml create mode 100644 Gemfile create mode 100644 fastlane/.gitignore create mode 100644 fastlane/Fastfile create mode 100644 fastlane/Pluginfile create mode 100644 fastlane/README.md diff --git a/.github/workflows/release_authenticator.yml b/.github/workflows/release_authenticator.yml new file mode 100644 index 0000000..b845534 --- /dev/null +++ b/.github/workflows/release_authenticator.yml @@ -0,0 +1,57 @@ +name: Release Authenticator +on: + push: + branches: [ release ] + +permissions: + id-token: write + contents: write + +jobs: + unit-tests: + name: Run Unit Tests + uses: ./.github/workflows/unit_tests.yml + with: + identifier: 'workflow-call-unit-test' + + release: + environment: Release + name: Release new Authenticator version + needs: [unit-tests] + runs-on: macos-latest + env: + GITHUB_EMAIL: aws-amplify-ops@amazon.com + GITHUB_USER: aws-amplify-ops + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@8c3f20df09ac63af7b3ae3d7c91f105f857d8497 #v4 + with: + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + role-session-name: ${{ format('{0}.release', github.run_id) }} + aws-region: ${{ secrets.AWS_REGION }} + mask-aws-account-id: true + + - id: retrieve-token + name: Retrieve Token + env: + DEPLOY_SECRET_ARN: ${{ secrets.DEPLOY_SECRET_ARN }} + run: | + PAT=$(aws secretsmanager get-secret-value \ + --secret-id "$DEPLOY_SECRET_ARN" \ + | jq -r ".SecretString | fromjson | .Credential") + echo "token=$PAT" >> $GITHUB_OUTPUT + + - name: Checkout repo + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + fetch-depth: 10 + token: ${{steps.retrieve-token.outputs.token}} + + - name: Setup Ruby + uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0 + with: + ruby-version: '3.2.1' + bundler-cache: true + + - name: Release Authenticator + run: bundle exec fastlane release \ No newline at end of file diff --git a/.github/workflows/release_kickoff.yml b/.github/workflows/release_kickoff.yml new file mode 100644 index 0000000..908a0ee --- /dev/null +++ b/.github/workflows/release_kickoff.yml @@ -0,0 +1,18 @@ +name: Release - Kick-off +on: + workflow_dispatch: + +permissions: + pull-requests: write + +jobs: + release: + name: Release + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - name: Create PR to push main to release branch + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: "gh pr create --title 'chore: kickoff release' --body 'kickoff release' --head main --base release" \ No newline at end of file diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index e3e8a5d..e7155b3 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -5,9 +5,19 @@ on: branches: [ main ] pull_request: branches: [ main ] + workflow_call: + inputs: + identifier: + required: true + type: string + +concurrency: + group: ${{ inputs.identifier || github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.ref_name != 'main'}} jobs: unit-test-ios: + name: iOS Unit Tests runs-on: macos-latest steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 @@ -28,6 +38,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} unit-test-macos: + name: macOS Unit Tests runs-on: macos-latest steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..00c7ad0 --- /dev/null +++ b/Gemfile @@ -0,0 +1,8 @@ +# Gemfile + +source 'https://rubygems.org' + +gem 'xcpretty', '0.3.0' +gem 'fastlane', '2.205.1' +eval_gemfile('fastlane/Pluginfile') + diff --git a/fastlane/.gitignore b/fastlane/.gitignore new file mode 100644 index 0000000..007b73e --- /dev/null +++ b/fastlane/.gitignore @@ -0,0 +1 @@ +test_output diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 0000000..8130dfc --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,64 @@ +opt_out_usage +default_platform(:swift) + +platform :swift do + before_all do + # Perform a fetch before inferring the next version + # to reduce race conditions with simultaneous pipelines attempting to create the same tag + sh('git', 'fetch', '--tags', '-f') + sh('git', 'fetch') + end + + desc "Create a release version by building and committing a changelog, pushing a tag to GitHub" + lane :release do + next_version, commits = calculate_next_release_version + + UI.message("Releasing version: #{next_version}") + + # Increment all specs and plists + increment_versions(version: next_version) + + # Update Changelog + changelog = build_changelog(version: next_version, commits: commits) + write_changelog(changelog: changelog, path: 'CHANGELOG.md') + + # Update Package dependencies + sh('bundle', 'exec', 'swift', 'package', 'update') + + # Commit and push + release_commit(version: next_version) + + # Create tag and push to origin + add_tag(version: next_version) + end + + desc "Increment versions" + private_lane :increment_versions do |options| + version = options[:version].to_s + set_key_value(file: "Sources/Authenticator/Constants/ComponentInformation.swift", key: "version", value: version) + end + + desc "Commit and push" + private_lane :release_commit do |options| + next_version = options[:version] + + sh('git', 'config', '--global', 'user.email', ENV['GITHUB_EMAIL']) + sh('git', 'config', '--global', 'user.name', ENV['GITHUB_USER']) + + commit_message = "chore: Release #{next_version} [skip ci]" + sh('git', 'commit', '-am', commit_message) + + # push to origin + sh('git', 'push', 'origin', 'release') + sh('git', 'push', 'origin', 'release:main') + end + + desc "Tag in git and push to GitHub" + private_lane :add_tag do |options| + next_version = options[:version] + next_tag = "#{next_version}" + + add_git_tag(tag: next_tag) + push_git_tags(tag: next_tag) + end +end diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile new file mode 100644 index 0000000..9750a5b --- /dev/null +++ b/fastlane/Pluginfile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-release_actions', git: 'https://github.com/aws-amplify/amplify-ci-support', branch: 'main', glob: 'src/fastlane/release_actions/*.gemspec' \ No newline at end of file diff --git a/fastlane/README.md b/fastlane/README.md new file mode 100644 index 0000000..cc85147 --- /dev/null +++ b/fastlane/README.md @@ -0,0 +1,24 @@ +fastlane documentation +---- + +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +```sh +xcode-select --install +``` + +For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) + +# Available Actions + +## Swift + +### swift release + +```sh +[bundle exec] fastlane swift release +``` + +Create a release version by building and committing a changelog, pushing a tag to GitHub \ No newline at end of file From 9f0cd72e8334d7ee75b7be633d2ca8fc93a2324e Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:00:01 -0400 Subject: [PATCH 2/4] chore: Updating setup-ruby version --- .github/workflows/release_authenticator.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release_authenticator.yml b/.github/workflows/release_authenticator.yml index b845534..0dbb3f5 100644 --- a/.github/workflows/release_authenticator.yml +++ b/.github/workflows/release_authenticator.yml @@ -48,7 +48,7 @@ jobs: token: ${{steps.retrieve-token.outputs.token}} - name: Setup Ruby - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0 + uses: ruby/setup-ruby@22fdc77bf4148f810455b226c90fb81b5cbc00a7 # v1.171.0 with: ruby-version: '3.2.1' bundler-cache: true From 345a018f7481e987fb7f77bf07623e06c73af2bf Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Wed, 15 May 2024 15:55:16 -0400 Subject: [PATCH 3/4] chore: Adding unstable releases. Removing need of a release branch and instead kicking off the release by merging into main --- .github/workflows/release_authenticator.yml | 44 +++++++++++++++-- .github/workflows/release_kickoff.yml | 47 +++++++++++++++--- fastlane/Fastfile | 53 ++++++++++++++++----- 3 files changed, 119 insertions(+), 25 deletions(-) diff --git a/.github/workflows/release_authenticator.yml b/.github/workflows/release_authenticator.yml index 0dbb3f5..85cb14e 100644 --- a/.github/workflows/release_authenticator.yml +++ b/.github/workflows/release_authenticator.yml @@ -1,13 +1,28 @@ name: Release Authenticator on: push: - branches: [ release ] + branches: [ main ] permissions: id-token: write contents: write jobs: + determine-release-type: + name: Determine the release type + runs-on: ubuntu-latest + outputs: + release-type: ${{ steps.release-type.outputs.value }} + steps: + - id: release-type + run: | + if ${{ github.event.head_commit.author.username == 'github-actions[bot]' && startsWith(github.event.head_commit.message, 'chore: Release ') }}; then + VALUE=stable + else + VALUE=unstable + fi + echo "value=$VALUE" >> $GITHUB_OUTPUT + unit-tests: name: Run Unit Tests uses: ./.github/workflows/unit_tests.yml @@ -16,8 +31,8 @@ jobs: release: environment: Release - name: Release new Authenticator version - needs: [unit-tests] + name: Release new Authenticator ${{ needs.determine-release-type.outputs.release-type }} version + needs: [determine-release-type, unit-tests] runs-on: macos-latest env: GITHUB_EMAIL: aws-amplify-ops@amazon.com @@ -53,5 +68,24 @@ jobs: ruby-version: '3.2.1' bundler-cache: true - - name: Release Authenticator - run: bundle exec fastlane release \ No newline at end of file + - name: Release unstable version + if: needs.determine-release-type.outputs.release-type == 'unstable' + env: + GH_TOKEN: ${{ github.token }} + run: bundle exec fastlane unstable_release + + - name: Determine stable release version + id: determine-release-version + if: needs.determine-release-type.outputs.release-type == 'stable' + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + with: + result-encoding: string + script: | + const matches = `${{ github.event.head_commit.message }}`.match(/[0-9]+\.[0-9]+\.[0-9]+/) ?? [] + return matches.length > 0 ? matches[0] : "" + + - name: Release stable version + if: steps.determine-release-version.outputs.result != '' + env: + GH_TOKEN: ${{ github.token }} + run: bundle exec fastlane stable_release version:${{ steps.determine-release-version.outputs.result }} \ No newline at end of file diff --git a/.github/workflows/release_kickoff.yml b/.github/workflows/release_kickoff.yml index 908a0ee..9b4bb7f 100644 --- a/.github/workflows/release_kickoff.yml +++ b/.github/workflows/release_kickoff.yml @@ -3,16 +3,49 @@ on: workflow_dispatch: permissions: + id-token: write pull-requests: write jobs: release: - name: Release - runs-on: ubuntu-latest - + environment: Release + name: Kick off new Authenticator release + runs-on: macos-latest + env: + GITHUB_EMAIL: aws-amplify-ops@amazon.com + GITHUB_USER: aws-amplify-ops steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b - - name: Create PR to push main to release branch + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@8c3f20df09ac63af7b3ae3d7c91f105f857d8497 #v4 + with: + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + role-session-name: ${{ format('{0}.release', github.run_id) }} + aws-region: ${{ secrets.AWS_REGION }} + mask-aws-account-id: true + + - id: retrieve-token + name: Retrieve Token + env: + DEPLOY_SECRET_ARN: ${{ secrets.DEPLOY_SECRET_ARN }} + run: | + PAT=$(aws secretsmanager get-secret-value \ + --secret-id "$DEPLOY_SECRET_ARN" \ + | jq -r ".SecretString | fromjson | .Credential") + echo "token=$PAT" >> $GITHUB_OUTPUT + + - name: Checkout repo + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + fetch-depth: 10 + token: ${{steps.retrieve-token.outputs.token}} + + - name: Setup Ruby + uses: ruby/setup-ruby@22fdc77bf4148f810455b226c90fb81b5cbc00a7 # v1.171.0 + with: + ruby-version: '3.2.1' + bundler-cache: true + + - name: Kick off Authenticator release env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: "gh pr create --title 'chore: kickoff release' --body 'kickoff release' --head main --base release" \ No newline at end of file + GH_TOKEN: ${{ github.token }} + run: bundle exec fastlane kickoff_release \ No newline at end of file diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 8130dfc..f058242 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -9,12 +9,11 @@ platform :swift do sh('git', 'fetch') end - desc "Create a release version by building and committing a changelog, pushing a tag to GitHub" - lane :release do + desc "Kickoff the next release by updating the changelog, updating the component version, and creating a PR to main" + lane :kickoff_release do next_version, commits = calculate_next_release_version - UI.message("Releasing version: #{next_version}") - + UI.message("Kicking off new release for version: #{next_version}") # Increment all specs and plists increment_versions(version: next_version) @@ -25,11 +24,16 @@ platform :swift do # Update Package dependencies sh('bundle', 'exec', 'swift', 'package', 'update') + # Create and push the new branch + release_branch = "release/#{next_version}" + sh('git', 'checkout', '-b', release_branch) + sh('git', 'push', '--set-upstream', 'origin', release_branch) + # Commit and push - release_commit(version: next_version) + pr_title = release_commit(version: next_version).to_s - # Create tag and push to origin - add_tag(version: next_version) + # Open the PR to main + sh('gh', 'pr', 'create', '--title', pr_title, '--body', 'Kicking off new release', '--base', 'main', '--head', release_branch) end desc "Increment versions" @@ -45,18 +49,41 @@ platform :swift do sh('git', 'config', '--global', 'user.email', ENV['GITHUB_EMAIL']) sh('git', 'config', '--global', 'user.name', ENV['GITHUB_USER']) - commit_message = "chore: Release #{next_version} [skip ci]" + commit_message = "chore: Release #{next_version}" sh('git', 'commit', '-am', commit_message) + sh('git', 'push') + commit_message + end + + desc "Create a pre-release version by pushing a new tag to GitHub" + lane :unstable_release do + next_version = calculate_next_canary_version + + UI.message("Releasing Authenticator unstable version: #{next_version}") + + # Create tag and push to origin + add_tag(version: next_version) + end + + desc "Create a release version by pushing a new tag to GitHub and creating a new draft release" + lane :stable_release do |options| + next_version = options[:version] + + UI.message("Releasing Authenticator version: #{next_version}") - # push to origin - sh('git', 'push', 'origin', 'release') - sh('git', 'push', 'origin', 'release:main') + # Create and push the new tag + add_tag(version: next_version) + + # Create draft release + release_date = sh("echo $(date +%F)") + release_title = "#{next_version} (#{release_date})" + sh('gh', 'release', 'create', next_version, '--draft', '--title', release_title) end + desc "Tag in git and push to GitHub" private_lane :add_tag do |options| - next_version = options[:version] - next_tag = "#{next_version}" + next_tag = options[:version].to_s add_git_tag(tag: next_tag) push_git_tags(tag: next_tag) From a562e5f2b5406575069bf37cad412e85f441c9d4 Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Thu, 16 May 2024 11:38:58 -0400 Subject: [PATCH 4/4] chore: Unit tests are now run as part of release, no need to run them on push to main --- .github/workflows/unit_tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index e7155b3..d234b94 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -1,8 +1,6 @@ name: Run Unit Tests on: - push: - branches: [ main ] pull_request: branches: [ main ] workflow_call: