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

Release management in CI #18398

merged 16 commits into from
May 12, 2023

Conversation

oguzkocer
Copy link
Contributor

@oguzkocer oguzkocer commented May 10, 2023

This PR adds the necessary configurations to handle the project's release management in CI. It closely follows the approach we've explored in release-toolkit-demo project and discussed internally in our RFCs.

There are a few moving parts to be aware of:

  1. There are new Buildkite triggers to start release management jobs. These are contained in fastlane/lanes/release_management_in_ci.rb. We intend to remove these triggers and use curl instead.
  2. There are new pipelines for each release management step, such as .buildkite/code-freeze.yml, .buildkite/complete-code-freeze.yml etc. These are pretty straightforward as they just call the relevant lane after some basic configuration.
  3. There are a few new Buildkite helper commands. .buildkite/commands/configure-git-for-release-management.sh configures the git client, which we intend to move to our agents. .buildkite/commands/checkout-release-branch.sh checks out the release branch which is necessary because Buildkite starts the job in a detached state and we need to be on a branch to be able to commit and push the changes. Similarly .buildkite/commands/checkout-editorial-branch.sh checks out the editorial branch which is a parameter in the job's trigger.
  4. We are temporarily using the remove/git-push-actions release-toolkit branch which is already approved. I intend to create the new release tomorrow. As a result of this, you'll notice a few additions of push_to_git_remote.
  5. The rest of the changes are in the release & localization lanes. They are mostly related to creating an intermediate branch, pushing the changes to remote and creating a pull request.
  6. Note that downloading translations will likely not work well in CI in this current iteration. That's because we get 429: Too Many Requests errors as we try to download several translations and we need to manually confirm to retry. I'm working on a possible fix for this, but it won't be part of this PR.

To test:

Unfortunately there is no way to test the full release flow directly in WPAndroid. However, we used release-toolkit-demo project to test this implementation before bringing it to WPAndroid. So, hopefully any issues we might experience will be minimal.

I was able the test updating release notes flow and it verified that the general setup is working correctly. It's a bit cumbersome to test this and since it's in CI, there isn't anything new to expect, so I suggest skipping this testing step.

We expect some minor issues with the initial implementation, but I am in a position to quickly address them as this project's release manager.

Regression Notes

  1. Potential unintended areas of impact
    Parts of release management might break as we move it to CI.

  2. What I did to test those areas of impact (or what existing automated tests I relied on)
    N/A

  3. What automated tests I added (or what prevented me from doing so)
    N/A

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

UI Changes testing checklist:

N/A

@oguzkocer oguzkocer added this to the 22.4 milestone May 10, 2023
@wpmobilebot
Copy link
Contributor

wpmobilebot commented May 10, 2023

Jetpack📲 You can test the changes from this Pull Request in Jetpack by scanning the QR code below to install the corresponding build.
App NameJetpack Jetpack
FlavorJalapeno
Build TypeDebug
Versionpr18398-0af7b97
Commit0af7b97
Direct Downloadjetpack-prototype-build-pr18398-0af7b97.apk
Note: Google Login is not supported on these builds.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented May 10, 2023

WordPress📲 You can test the changes from this Pull Request in WordPress by scanning the QR code below to install the corresponding build.
App NameWordPress WordPress
FlavorJalapeno
Build TypeDebug
Versionpr18398-0af7b97
Commit0af7b97
Direct Downloadwordpress-prototype-build-pr18398-0af7b97.apk
Note: Google Login is not supported on these builds.

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.

@oguzkocer oguzkocer force-pushed the release-management-in-ci branch from 1e8c36e to 686f0f6 Compare May 10, 2023 21:01
Gemfile Outdated
# 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.

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.

@@ -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.

title: title,
head: Fastlane::Helper::GitHelper.current_git_branch,
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.

api_token: ENV['GITHUB_TOKEN'],
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.


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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Our goal is to remove these triggers from fastlane. We'll likely use curl for this, so that release managers don't need to have anything setup in their local environment. However, since we already have buildkite_trigger_build helper, it made sense to use it during the initial implementation phase.

Copy link
Contributor

Choose a reason for hiding this comment

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

I like that this is nicely separated out for easy removal later!

@oguzkocer oguzkocer marked this pull request as ready for review May 11, 2023 03:39
@oguzkocer oguzkocer requested a review from a team May 11, 2023 03:39
@mokagio mokagio added the Do Not Merge In PRs with this label, our automation will fail a require check, preventing accidental merging label May 11, 2023
@mokagio
Copy link
Contributor

mokagio commented May 11, 2023

Please DO NOT merge this PR, as we need to do a release-toolkit release first.

Created and added the "Do Not Merge" label, and Peril picked it up.

image


# 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 👏

Copy link
Contributor

@mokagio mokagio left a comment

Choose a reason for hiding this comment

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

I started looking at this but I don't have the energy to give it the attention it deserves right now.

Just a not. Looking at the various new pipelines and how similar they are, it occurred to me that we might make the setup easier to maintain – as a possible followup! – by generating the pipeline. See the dynamic pipelines docs.

@oguzkocer
Copy link
Contributor Author

Just a not. Looking at the various new pipelines and how similar they are, it occurred to me that we might make the setup easier to maintain – as a possible followup! – by generating the pipeline. See the dynamic pipelines docs.

It's definitely worth exploring. I think the main benefit we should look to gain from that should be to get rid of the boilerplate part but still keep the command steps. As long as we keep each file separate - or somehow put it all in a small and easy to read file, then it's a net positive for us. However, if it makes it harder to navigate the code, then I don't think we should do it.

@oguzkocer oguzkocer requested a review from a team May 11, 2023 19:28
Copy link
Contributor

@jkmassel jkmassel left a comment

Choose a reason for hiding this comment

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

Looks solid to me!

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!

@@ -0,0 +1,10 @@
def create_release_management_pull_request(base_branch, title)
create_pull_request(
api_token: ENV['GITHUB_TOKEN'],
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.

Copy link
Contributor

Choose a reason for hiding this comment

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

I like that this is nicely separated out for easy removal later!

@oguzkocer oguzkocer removed the Do Not Merge In PRs with this label, our automation will fail a require check, preventing accidental merging label May 12, 2023
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.


new_version = android_get_app_version()
trigger_beta_build(branch_to_build: "release/#{new_version}")

create_release_management_pull_request('trunk', "Merge #{new_version} code freeze to trunk")
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick. Since we dropped the develop-trunk setup, I stopped adding "to trunk" in my PRs because that's the branch where usually release PRs land.

Suggested change
create_release_management_pull_request('trunk', "Merge #{new_version} code freeze to trunk")
create_release_management_pull_request('trunk', "Merge #{new_version} code freeze")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With release management in CI, not all PRs target the trunk branch. Some of them target the release branch, so I think it's useful to have this information.

setfrozentag(repository: GHHELPER_REPO, milestone: version['name'], freeze: false)
create_new_milestone(repository: GHHELPER_REPO)
close_milestone(repository: GHHELPER_REPO, milestone: version['name'])

# Trigger release build
trigger_release_build(branch_to_build: "release/#{version['name']}")

create_release_management_pull_request('trunk', "Merge #{app_version} final to trunk")
Copy link
Contributor

Choose a reason for hiding this comment

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

Same rationale as above.

Suggested change
create_release_management_pull_request('trunk', "Merge #{app_version} final to trunk")
create_release_management_pull_request('trunk', "Merge #{app_version} final")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same rationale as above. 😅

buildkite_pipeline: BUILDKITE_PIPELINE,
branch: "release/#{release_version}",
pipeline_file: 'complete-code-freeze.yml',
message: 'Complete Code Freeze in CI',

This comment was marked as duplicate.

Copy link
Contributor

@mokagio mokagio left a comment

Choose a reason for hiding this comment

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

Only left nitpicks that have little to do with the actual implementation. Things are looking pretty good 😄

Co-authored-by: Gio Lodi <gio.lodi@automattic.com>
@peril-wordpress-mobile
Copy link

Warnings
⚠️ This PR is assigned to a milestone which is closing in less than 4 days Please, make sure to get it merged by then or assign it to a later expiring milestone

Generated by 🚫 dangerJS

Co-authored-by: Gio Lodi <gio.lodi@automattic.com>
@oguzkocer
Copy link
Contributor Author

Thank you for the review @mokagio! I've applied all your suggestions except for dropping to trunk part of the PR titles. I left a comment about it, but I'll re-iterate it here. With release management in CI, not all PRs will be targeting trunk, so I think it's good to be able to see that information at a glance - especially when the GitHub url is unfurled in Slack or p2.

@oguzkocer oguzkocer merged commit fbc44e5 into trunk May 12, 2023
@oguzkocer oguzkocer deleted the release-management-in-ci branch May 12, 2023 05:09
git config --global user.name "Automattic Release Bot"

# 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! 🙇‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants