diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1affcbee4c..84e926ef9b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -5,19 +5,28 @@ on: workflow_dispatch: inputs: product: - description: "Which app are you updating" + description: "Which app is being released." type: choice options: - Password Manager - Authenticator version-code: - description: "Build number to promote. Overrides default of GitHub run number." + description: "Build number to promote to production." required: true type: number rollout-percentage: - description: "Starting percentage of users who will receive this version update." + description: "Percentage of users who will receive this version update." + required: true + type: choice + options: + - 10% + - 30% + - 50% + - 100% + release-notes: + description: "Change notes to be included with this release." + type: string required: true - type: number env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -33,6 +42,9 @@ jobs: name: Promote build to Production in Play Store steps: + - name: Check out repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Configure Ruby uses: ruby/setup-ruby@ca041f971d66735f3e5ff1e21cc13e2d51e7e535 # v1.233.0 with: @@ -44,16 +56,6 @@ jobs: bundle config path vendor/bundle bundle install --jobs 4 --retry 3 - - name: Check - run: bundle exec fastlane check - - - name: Upload test reports on failure - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: failure() - with: - name: test-reports - path: app/build/reports/tests/ - - name: Log in to Azure uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: @@ -73,35 +75,45 @@ jobs: --name app_upload-keystore.jks --file ${{ github.workspace }}/keystores/app_upload-keystore.jks --output none az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ --name play_creds.json --file ${{ github.workspace }}/secrets/play_creds.json --output none - az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ - --name google-services.json --file ${{ github.workspace }}/app/src/standardRelease/google-services.json --output none az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ - --name google-services.json --file ${{ github.workspace }}/app/src/standardBeta/google-services.json --output none + --name app_beta_play-keystore.jks --file ${{ github.workspace }}/keystores/app_beta_play-keystore.jks --output none + az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ + --name app_beta_upload-keystore.jks --file ${{ github.workspace }}/keystores/app_beta_upload-keystore.jks --output none + az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ + --name google-services.json --file ${{ github.workspace }}/app/src/standardRelease/google-services.json --output none - - name: Promote Password Manager Play Store version - if: ${{inputs.product == 'Password Manager'}} + - name: Format Release Notes + run: | + FORMATTED_MESSAGE="$(echo "${{ inputs.release-notes }}" | sed 's/ /\n/g')" + echo "RELEASE_NOTES<> $GITHUB_ENV + echo "$FORMATTED_MESSAGE" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + - name: Promote Play Store version to production env: PLAY_KEYSTORE_PASSWORD: ${{ secrets.PLAY_BETA_KEYSTORE_PASSWORD }} PLAY_KEY_PASSWORD: ${{ secrets.PLAY_BETA_KEY_PASSWORD }} + VERSION_CODE: ${{ inputs.version-code }} + ROLLOUT_PERCENTAGE: ${{ inputs.rollout-percentage }} + PRODUCT: ${{ inputs.product }} run: | - bundle exec fastlane run promoteToProduction \ - versionCode: ${{ inputs.version-code }} \ - rolloutPercentage: ${{ inputs.rollout-percentage }} \ - storePassword:${{ env.PLAY_KEYSTORE_PASSWORD }} \ - keyAlias:upload \ - keyPassword:${{ env.PLAY_KEY_PASSWORD }} \ - packageName: "com.x8bit.bitwarden" + if [ "$PRODUCT" = "Password Manager" ]; then + PACKAGE_NAME="com.x8bit.bitwarden" + elif [ "$PRODUCT" = "Authenticator" ]; then + PACKAGE_NAME="com.bitwarden.authenticator" + else + echo "Unsupported product: $PRODUCT" + exit 1 + fi - - name: Promote Authenticator Play Store version - if: ${{inputs.product == 'Authenticator'}} - env: - PLAY_KEYSTORE_PASSWORD: ${{ secrets.PLAY_BETA_KEYSTORE_PASSWORD }} - PLAY_KEY_PASSWORD: ${{ secrets.PLAY_BETA_KEY_PASSWORD }} - run: | - bundle exec fastlane promoteAuthenticatorToProduction \ - versionCode: ${{ inputs.version-code }} \ - rolloutPercentage: ${{ inputs.rollout-percentage }} \ - storePassword:${{ env.PLAY_KEYSTORE_PASSWORD }} \ - keyAlias:upload \ - keyPassword:${{ env.PLAY_KEY_PASSWORD }} - packageName: "com.bitwarden.authenticator" + decimal=$(echo "scale=2; ${ROLLOUT_PERCENTAGE/\%/} / 100" | bc) + + bundle exec fastlane updateReleaseNotes \ + releaseNotes:"$RELEASE_NOTES" \ + versionCode:"$VERSION_CODE" + + bundle exec fastlane promoteToProduction \ + versionCode:"$VERSION_CODE" \ + rolloutPercentage:$decimal \ + packageName:"$PACKAGE_NAME"\ + releaseNotes:"$RELEASE_NOTES" diff --git a/fastlane/Fastfile b/fastlane/Fastfile index f66773f18b..37d56e4933 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -185,16 +185,6 @@ platform :android do ) end - desc "Generate release notes" - lane :generateReleaseNotes do |options| - branchName = `git rev-parse --abbrev-ref HEAD`.chomp() - releaseNotes = changelog_from_git_commits( - commits_count: 1, - pretty: "%s%n#{options[:repoName]}/#{branchName} @ %h %n %n#{options[:actionUrl]}" - ) - releaseNotes - end - desc "Publish Release Play Store artifacts to Firebase App Distribution" lane :distributeReleasePlayStoreToFirebase do |options| releaseNotes = generateReleaseNotes( @@ -265,6 +255,16 @@ platform :android do ) end + desc "Generate release notes" + lane :generateReleaseNotes do |options| + branchName = `git rev-parse --abbrev-ref HEAD`.chomp() + releaseNotes = changelog_from_git_commits( + commits_count: 1, + pretty: "%s%n#{options[:repoName]}/#{branchName} @ %h %n %n#{options[:actionUrl]}" + ) + releaseNotes + end + # Authenticator desc "Apply build version information" fastlane_require "time" @@ -385,32 +385,50 @@ platform :android do ) end - desc "Update release notes for all locales." - lane :updateReleaseNotes do - changelog = {options[:releaseNotes]} - version_code = {options[:versionCode]} - locales = ["ca", "cs-CZ", "da-DK", "de-DE", "en-US", "es-ES", "et", "fi-FI", "fr-FR", "hr", "hu-HU", "id", "it-IT", "iw-IL", "ja-JP", "nl-NL", "pl-PL", "pt-BR", "pt-PT", "ro", "ru-RU", "sk", "sv-SE", "tr-TR", "uk", "vi", "zh-CN", "zh-TW"] + desc "Retrieve build from Github releases" + lane :retrieveBuildFromGithub do |options| + version_codes = Actions.lane_context[SharedValues::GOOGLE_PLAY_TRACK_VERSION_CODES] + UI.message("Version codes in beta track: #{version_codes}") + end + + desc "Update release notes for all locales." + lane :updateReleaseNotes do |options| + changelog = options[:releaseNotes] + version_code = options[:versionCode] + auth_locales = ["en-US"] + pw_manager_locales = ["ca", "cs-CZ", "da-DK", "de-DE", "en-US", "es-ES", "et", "fr-FR", "hr", "hu-HU", "id", "it-IT", "iw-IL", "ja-JP", "nl-NL", "pl-PL", "pt-BR", "pt-PT", "ro", "ru-RU", "sk", "sv-SE", "tr-TR", "uk", "vi", "zh-CN", "zh-TW"] + if options[:packageName] == "com.bitwarden.authenticator" + locales = auth_locales + else + locales = pw_manager_locales + end locales.each do |locale| - dir = "fastlane/metadata/#{locale}/changelogs" + dir = "metadata/android/#{locale}/changelogs" FileUtils.mkdir_p(dir) File.write("#{dir}/#{version_code}.txt", changelog) end end desc "Promote to production." - lane :promoteToProduction do - supply( - json_key: options[:serviceCredentialsFile], + lane :promoteToProduction do |options| + supply_options = { package_name: options[:packageName], - track: "internal", # The current track - track_promote_to: "production", # Target track + version_code: options[:versionCode], + track: "Internal" + track_promote_to: "production", # production is case sensitive skip_upload_apk: true, skip_upload_aab: true, - skip_upload_metadata: true, - release_status: "inProgress" - rollout: options[:rolloutPercentage] - # skip_upload_changelogs: true - ) + skip_upload_metadata: false + } + + if options[:rolloutPercentage].to_f < 1 + supply_options[:track_promote_release_status] = "inProgress" + supply_options[:rollout] = options[:rolloutPercentage] + else + supply_options[:track_promote_release_status] = "complete" + end + + supply(supply_options) end end