Skip to content

Release management in CI #18398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .buildkite/beta-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.15.0
- automattic/a8c-ci-toolkit#2.15.1

steps:
#################
Expand Down
15 changes: 15 additions & 0 deletions .buildkite/code-freeze.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Nodes with values to reuse in the pipeline.
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.15.1

steps:
- label: "Code Freeze"
plugins: *common_plugins
command: |
.buildkite/commands/configure-git-for-release-management.sh
install_gems
bundle exec fastlane code_freeze skip_confirm:true
22 changes: 22 additions & 0 deletions .buildkite/commands/checkout-editorial-branch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash -eu

# EDITORIAL_BRANCH is passed as an environment variable from fastlane to Buildkite
#
if [[ -z "${EDITORIAL_BRANCH}" ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL about this approach to avoid the set -u from the shebang to fail the script at this point because of an unbound access. Neat 👏

echo "EDITORIAL_BRANCH is not set."
exit 1
fi

# RELEASE_VERSION is passed as an environment variable from fastlane to Buildkite
# Even though RELEASE_VERSION is not directly used in this script, it's necessary to update
# the app store strings. Having this check here keeps the buildkite pipeline cleaner. Later on,
# if we don't want it here, we can move it to a separate script file.
if [[ -z "${RELEASE_VERSION}" ]]; then
echo "RELEASE_VERSION is not set."
exit 1
fi

# Buildkite, by default, checks out a specific commit. When we update the app store strings, we open
# a PR from the current branch. So, we need to checkout the `EDITORIAL_BRANCH`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the difference that we wouldn't be able to open the PR if we were on a commit (detached HEAD?)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't add a new commit in a detached HEAD. When we update the app store strings, we need to create new commits and push it to remote.

git fetch origin "$EDITORIAL_BRANCH"
git checkout "$EDITORIAL_BRANCH"
14 changes: 14 additions & 0 deletions .buildkite/commands/checkout-release-branch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash -eu

# RELEASE_VERSION is passed as an environment variable from fastlane to Buildkite
#
if [[ -z "${RELEASE_VERSION}" ]]; then
echo "RELEASE_VERSION is not set."
exit 1
fi

# Buildkite, by default, checks out a specific commit. For many release actions, we need to be
# on a release branch instead.
BRANCH_NAME="release/${RELEASE_VERSION}"
git fetch origin "$BRANCH_NAME"
git checkout "$BRANCH_NAME"
10 changes: 10 additions & 0 deletions .buildkite/commands/configure-git-for-release-management.sh
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We intend to bring this configuration to our agents, so that we don't have to do it in every pipeline.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash -eu

# Git command line client is not configured in Buildkite. Temporarily, we configure it in each step.
# Later on, we should be able to configure the agent instead.
curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | sed -e 's/^/github.com /' >> ~/.ssh/known_hosts
git config --global user.email "mobile+wpmobilebot@automattic.com"
git config --global user.name "Buildkite"

# Buildkite is currently using the https url to checkout. We need to override it to be able to use the deploy key.
git remote set-url origin git@github.com:wordpress-mobile/WordPress-Android.git
Copy link
Contributor

@AliSoftware AliSoftware May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 I wonder if it would be better to make this a bit more generic, like:

REPO_NO_TRAILING=${BUILDKITE_REPO%/}
git remote set-url origin  ${REPO_NO_TRAILING/#https:\/\/github.com\//git@github:}

Or alternatively (inspired by this):

REPO_SLUG=$(basename $(dirname "$BUILDKITE_REPO"))/$(basename "$BUILDKITE_REPO%.git")
git remote set-url origin git@github.com:${REPO_SLUG}.git

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this was in a toolkit repo, it'd make sense to go with a generic version. However, since this is part of WordPress-Android, I think this just makes it harder to understand the code.

Furthermore, it looks like I forgot to mention that this is a temporary issue specific to WordPress-Android. We should not be using the https url to clone in the first place. I just didn't have a chance to figure out why this is the case for WordPress-Android. I think we used to have a specific configuration for WPAndroid, but I couldn't find it yet.

For example, we don't need this bit in release-toolkit-demo. I also checked FluxC & WCAndroid and they both use the ssh url.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aaah.. and I think I might have found the culprit. All this time I've been checking the Buildkite settings' Checkout using: section which says that we are using ssh to checkout. However, I just checked the terraform and the repository field for WPAndroid is https://github.com/wordpress-mobile/WordPress-Android/. I compared this against WPiOS, WCAndroid & FluxC and they all use the ssh url. So, I think we'll be able to get rid of this configuration all together.

Having said that, I hope my previous logic also made sense in terms of keeping the specific url.

Copy link
Contributor

@AliSoftware AliSoftware May 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this was in a toolkit repo, it'd make sense to go with a generic version. However, since this is part of WordPress-Android, I think this just makes it harder to understand the code.

🤦‍♂️ I've reviewed so many PRs in the past few days that I think I lost track of which repo each PR was about, and since I reviewed a PR about buildkite-ci repo just before this one, I think I didn't realize I was now reviewing a WPAndroid repo when I switched to this review 🤦‍♂️🤦 Sorry 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries at all 🤗

I've reviewed so many PRs in the past few days

I noticed ❤️ - thank you for doing that! 🙇‍♂️

16 changes: 16 additions & 0 deletions .buildkite/complete-code-freeze.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Nodes with values to reuse in the pipeline.
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.15.1

steps:
- label: "Complete Code Freeze"
plugins: *common_plugins
command: |
.buildkite/commands/configure-git-for-release-management.sh
.buildkite/commands/checkout-release-branch.sh
install_gems
bundle exec fastlane complete_code_freeze skip_confirm:true
16 changes: 16 additions & 0 deletions .buildkite/finalize-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Nodes with values to reuse in the pipeline.
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.15.1

steps:
- label: "Finalize release"
plugins: *common_plugins
command: |
.buildkite/commands/configure-git-for-release-management.sh
.buildkite/commands/checkout-release-branch.sh
install_gems
bundle exec fastlane finalize_release skip_confirm:true
15 changes: 15 additions & 0 deletions .buildkite/new-beta-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Nodes with values to reuse in the pipeline.
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.15.1

steps:
- label: "New Beta Release"
plugins: *common_plugins
command: |
.buildkite/commands/configure-git-for-release-management.sh
install_gems
bundle exec fastlane new_beta_release skip_confirm:true
2 changes: 1 addition & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.14.0
- automattic/a8c-ci-toolkit#2.15.1

steps:
#################
Expand Down
2 changes: 1 addition & 1 deletion .buildkite/release-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.14.0
- automattic/a8c-ci-toolkit#2.15.1

steps:
#################
Expand Down
16 changes: 16 additions & 0 deletions .buildkite/update-release-notes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Nodes with values to reuse in the pipeline.
common_params:
# Common plugin settings to use with the `plugins` key.
- &common_plugins
- automattic/a8c-ci-toolkit#2.15.1

steps:
- label: "Update release notes"
plugins: *common_plugins
command: |
.buildkite/commands/configure-git-for-release-management.sh
.buildkite/commands/checkout-editorial-branch.sh
install_gems
bundle exec fastlane update_appstore_strings version:${RELEASE_VERSION}
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ gem 'nokogiri'

### Fastlane Plugins

gem 'fastlane-plugin-wpmreleasetoolkit', '~> 7.0'
#gem 'fastlane-plugin-wpmreleasetoolkit', '~> 7.0'
# gem 'fastlane-plugin-wpmreleasetoolkit', path: '../../release-toolkit'
# gem 'fastlane-plugin-wpmreleasetoolkit', git: 'https://github.com/wordpress-mobile/release-toolkit', branch: 'trunk'
gem 'fastlane-plugin-wpmreleasetoolkit', git: 'https://github.com/wordpress-mobile/release-toolkit', branch: 'remove/git-push-actions'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do a proper release before we merge this PR in.



### Gems needed only for generating Promo Screenshots
Expand Down
72 changes: 39 additions & 33 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,28 +1,49 @@
GIT
remote: https://github.com/wordpress-mobile/release-toolkit
revision: e26197f430a919e4d33bce7c69778870ca9e45af
branch: remove/git-push-actions
specs:
fastlane-plugin-wpmreleasetoolkit (7.0.0)
activesupport (>= 6.1.7.1)
bigdecimal (~> 1.4)
buildkit (~> 1.5)
chroma (= 0.2.0)
diffy (~> 3.3)
git (~> 1.3)
google-cloud-storage (~> 1.31)
nokogiri (~> 1.11)
octokit (~> 5.6)
parallel (~> 1.14)
plist (~> 3.1)
progress_bar (~> 1.3)
rake (>= 12.3, < 14.0)
rake-compiler (~> 1.0)

GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.6)
rexml
activesupport (7.0.4.2)
activesupport (7.0.4.3)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.1)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.721.0)
aws-sdk-core (3.170.0)
aws-partitions (1.762.0)
aws-sdk-core (3.172.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.63.0)
aws-sdk-kms (1.64.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.119.1)
aws-sdk-s3 (1.122.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
Expand All @@ -38,7 +59,7 @@ GEM
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
concurrent-ruby (1.2.0)
concurrent-ruby (1.2.2)
declarative (0.0.20)
diffy (3.4.2)
digest-crc (0.6.4)
Expand Down Expand Up @@ -77,7 +98,7 @@ GEM
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.212.1)
fastlane (2.212.2)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
Expand Down Expand Up @@ -116,26 +137,11 @@ GEM
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-wpmreleasetoolkit (7.0.0)
activesupport (>= 6.1.7.1)
bigdecimal (~> 1.4)
buildkit (~> 1.5)
chroma (= 0.2.0)
diffy (~> 3.3)
git (~> 1.3)
google-cloud-storage (~> 1.31)
nokogiri (~> 1.11)
octokit (~> 4.18)
parallel (~> 1.14)
plist (~> 3.1)
progress_bar (~> 1.3)
rake (>= 12.3, < 14.0)
rake-compiler (~> 1.0)
gh_inspector (1.1.3)
git (1.13.2)
git (1.18.0)
addressable (~> 2.8)
rchardet (~> 1.8)
google-apis-androidpublisher_v3 (0.35.0)
google-apis-androidpublisher_v3 (0.41.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.0)
addressable (~> 2.5, >= 2.5.1)
Expand Down Expand Up @@ -166,7 +172,7 @@ GEM
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.3.0)
googleauth (1.5.2)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
Expand All @@ -177,30 +183,30 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (1.12.0)
i18n (1.13.0)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.6.3)
jwt (2.7.0)
memoist (0.16.2)
mini_magick (4.12.0)
mini_mime (1.1.2)
mini_portile2 (2.8.1)
minitest (5.17.0)
mini_portile2 (2.8.2)
minitest (5.18.0)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
naturally (2.2.1)
nokogiri (1.14.2)
nokogiri (1.14.3)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (4.25.1)
octokit (5.6.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
options (2.3.2)
optparse (0.1.1)
os (1.1.4)
parallel (1.22.1)
parallel (1.23.0)
plist (3.7.0)
progress_bar (1.3.3)
highline (>= 1.6, < 3)
Expand Down Expand Up @@ -267,7 +273,7 @@ PLATFORMS

DEPENDENCIES
fastlane (~> 2)
fastlane-plugin-wpmreleasetoolkit (~> 7.0)
fastlane-plugin-wpmreleasetoolkit!
nokogiri
rmagick (~> 4.1)

Expand Down
2 changes: 2 additions & 0 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ REPOSITORY_NAME = 'WordPress-Android'
########################################################################
# Import domain-specific lanes
########################################################################
import 'helpers/github.rb'
import 'lanes/build.rb'
import 'lanes/localization.rb'
import 'lanes/release.rb'
import 'lanes/screenshots.rb'
import 'lanes/test.rb'
import 'lanes/release_management_in_ci.rb'

default_platform(:android)

Expand Down
10 changes: 10 additions & 0 deletions fastlane/helpers/github.rb
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure where the best place for this helper is. I've asked @jkmassel's opinion and he agreed that this approach made sense. However, if you have a suggestion, I'd be happy to apply it.

Note that I initially had this in the lanes/release_management_in_ci.rb file but I couldn't get it to work. I am now realizing that if I import that before the other lanes, that approach also would have worked. However, I like the separate file a bit better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a good start – long-term, might be good to see if we can turn it into a release toolkit action – I find that helpers generally end up there!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. To provide some context;

I initially intended to do this and created an internal discussion where Olivier pointed out that there is already a fastlane action for creating pull requests. That's when I moved on to adding it to the project instead. I went back and forth on where it belongs but decided to go with this initial implementation because this helper doesn't have much added value. However, at some point, I think it'll make sense to have separate helpers for code freeze, new beta, finalize release etc and then it'll make sense to move it to release-toolkit so we can use it in other projects as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. It makes sense to start local and extract/abstract later.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def create_release_management_pull_request(base_branch, title)
create_pull_request(
api_token: ENV['GITHUB_TOKEN'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fastlane uses ENV["GITHUB_API_TOKEN"] as the default whereas we are using ENV["GITHUB_TOKEN"]. Instead of adding another environment variable, I thought it'd be better to default to the existing one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sound 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good way to go. The reason we use that environment variable is that it's what OctoKit expects FWIW.

repo: GHHELPER_REPO,
title: title,
head: Fastlane::Helper::GitHelper.current_git_branch,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fastlane defaults to the current branch. However, it does so by using the git_branch helper which uses environment variables to override the value. We do not want this behavior which is why we added our own helper in wordpress-mobile/release-toolkit#463.

base: base_branch,
labels: 'Releases'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add reviewers field, but I wanted to skip that for now to not create extra noise. I have tested creating PRs a few times and will likely do a few more. Once everything settles down, it's easy enough to add this field.

)
end
11 changes: 8 additions & 3 deletions fastlane/lanes/localization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@
lane :update_appstore_strings do |options|
# If no `app:` is specified, call this for both WordPress and Jetpack
apps = options[:app].nil? ? %i[wordpress jetpack] : Array(options[:app]&.downcase&.to_sym)
version = options.fetch(:version, android_get_app_version)

apps.each do |app|
app_values = APP_SPECIFIC_VALUES[app]

metadata_folder = File.join(PROJECT_ROOT_FOLDER, 'WordPress', app_values[:metadata_dir])
version = options.fetch(:version, android_get_app_version)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version value is not application specific, in fact it's fetched from version.properties file which has a shared value. So, there is no harm in moving this outside of the loop and reuse the value in release_branch variable.


# <key in po file> => <path to txt file to read the content from>
files = {
Expand All @@ -126,6 +126,11 @@
commit_message: "Update #{app_values[:display_name]} `PlayStoreStrings.po` for version #{version}"
)
end

push_to_git_remote(tags: false)

release_branch = "release/#{version}"
create_release_management_pull_request(release_branch, "Merge #{version} editorialized release notes to #{release_branch}")
end

# Updates the metadata in the Play Store (Main store listing) from the content of `fastlane/{metadata|jetpack_metadata}/android/*/*.txt` files
Expand Down Expand Up @@ -173,7 +178,7 @@

skip_commit = options.fetch(:skip_commit, false)
skip_git_push = options.fetch(:skip_git_push, false)

# If no `app:` is specified, call this for both WordPress and Jetpack
apps = options[:app].nil? ? %i[wordpress jetpack] : Array(options[:app]&.to_s&.downcase&.to_sym)

Expand Down Expand Up @@ -213,7 +218,7 @@
source_file = key.to_s.start_with?('release_note_') ? 'release_notes.txt' : h[:desc]
FileUtils.cp(File.join(metadata_source_dir, source_file), File.join(download_path, 'en-US', h[:desc]))
end

unless skip_commit
git_add(path: download_path)
message = "Update #{app_values[:display_name]} metadata translations"
Expand Down
Loading