Skip to content
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

[Github-Actions-Workflows][Plugin-Release] Allow shipping a point-release for an older stable release #49082

Conversation

fullofcaffeine
Copy link
Member

@fullofcaffeine fullofcaffeine commented Mar 14, 2023

What?

Allows the creation + release (as atag in the WP SVN repo) of a point release for a given stable release, even when a newer (leaf/latest) stable release is present. The release should not be marked as latest when publishing and it will then run through a fork of the upload step that will ship it as a branch (under the branches directory) in the WP plugin repo (+ tag it under tags).

Why?

Currently, if (a) bug(s) is(are) found in a given version of Gutenberg and a fix is worked on, we can then ship this fix(es) as a patch release for that version. However, sometimes during the window of time the bug was reported/fix implemented, it could happen that the next stable release is shipped and that the next stable release isn't suitable to be released due to other newly-introduced issues. This effectively prevents a point release from being released for the previous stable release (which is not the latest anymore at this point). In the best case, the user must wait for the next version, which might take longer due to new issues that need to be worked out. This can be a dangerous proposition as a new version might bring more issues and needs further testing, especially in big multisite WordPress instances like Wordpress.com, effectively creating a significant bottleneck for shipping the fix(es). Because of that, we should be able to ship patch releases for older stable releases, even if a new stable release is already out, to have a faster turnaround when shipping bug-fixes. That's the goal of this changeset.

How?

  • By allowing version bumping for old stable releases even if a new stable release is already out in build-plugin-zip.yml (#)
  • By adding a new upload task to upload-release-to-plugin-repo.yml (#) that uploads that patch release as a branch (and tags it) to the WP plugins repo SVN. In this case, it leaves out trunk untouched in the SVN repo. This step only runs if the latest stable (fetched using the GH API) differs from the published version; otherwise, the upload as trunk runs instead. For this to work well, the GitHub draft release for this patch-release should NOT be marked as the latest release when it's published, or it will be considered the last release by the workflow and will replace trunk!*[0]
  • It shouldn't affect the other existing scenarios.

*[0] I don't see this as a huge problem, as long as we document this well. Also, this will often be done by people that understand the workflow and only in cases when an older patch release is needed when a new stable version is out, which shouldn't be too common (but still critical to ship when it happens!). Finally, if it happens that a patch-release for an older stable version ends in trunk because someone forgot to uncheck Set as the latest release when publishing, we can always revert the changes in the SVN repo manually.

Testing Instructions

Testing this isn't very pleasant, but possible. You'll need ngrok (or equivalent tunnel tool) and a local web-dav-enabled svn server exposed via the tunnel. I've used this one: https://hub.docker.com/r/elleflorio/svn-server.

  1. Fork the Gutenberg repo (not this repo). Make sure to recreate all the secrets from here. The ones needed are the SVN server username and password; the others are optional. Your new fork will not have any releases on the releases page, don't be surprised.
  2. Create a new release for the latest release tag, manually. I.e if the latest release for GB was 15.4.1, create a new release that points to this tag and is latest.
  3. Apply this diff to trunk and the the latest release branch (i.e release/15.4), and change the PLUGIN_REPO_URL to your tunnel URL.
  4. Ensure your svn server is running and exposed to the web!

Scenarios (happy paths)

Stable point release for the latest release

  1. Go to Actions->Build Gutenberg Plugin Zip, leave trunk as the branch, and in the rc or stable? input box, type stable.
  2. Once the action finishes, go to the /releases page, you should see a draft for the new patch release; click the pencil icon to edit it and then Publish. You should leave Set as the latest release checked here.
  3. Go to actions again and open the Update Changelog and upload Gutenberg plugin to WordPress.org plugin repo (you will need to click Show more workflows in the sidebar to see it).
  4. Once it finishes, you should see the release published under /releases as latest and also in your SVN repo under trunk and under tags/$VERSION where $VERSION is the bumped version for this patch release.

Create a RC in order to create a new stable release

Let's create an RC to create a new stable release later:

  1. Go to Actions->Build Gutenberg Plugin Zip, leave trunk as the branch, and in the rc or stable? input box, type rc.
  2. Once the action finishes, go to the /releases page, you should see a draft for the new patch release, click the pencil icon to edit it and then Publish. You should leave Set as prerelease checked.

Now we have a new release branch and are ready to create a new stable release!

Create and publish a new stable release

This will set the ground for the last test, which will be to ship a point release for your previous stable release.

  1. Go to Actions->Build Gutenberg Plugin Zip, leave trunk as the branch, and in the rc or stable? input box, type stable.
  2. Once the action finishes, go to the /releases page; you should see a draft for the new patch release; click the pencil icon to edit it and then Publish. You should leave Set as the latest release checked here.
  3. Go to actions again and open the Update Changelog and upload Gutenberg plugin to WordPress.org plugin repo (you must click Show more workflows in the sidebar to see it).
  4. Once it finishes, you should see the release published under /releases as latest and also in your SVN repo under trunk and under tags/$VERSION where $VERSION is the new stable release.

Create and publish a patch release for the previous stable release

This is the scenario that has been implemented in this changeset. Let's go ahead and test it out.

  1. Go to Actions->Build Gutenberg Plugin Zip, select your previous stable release branch (i.e release/15.4 if the new one is release/15.5) as the branch, and in the rc or stable? input box, type stable.
  2. Once the action finishes, go to the /releases page; you should see a draft for the new patch release; click the pencil icon to edit it and then Publish. IMPORTANT: You msut UNCHECK Set as the latest release checkbox, or it will be considered a regular latest release and will be pushed to the trunk of the WP SVN repo!
  3. Go to actions again and open the Update Changelog and upload Gutenberg plugin to WordPress.org plugin repo (you will need to click Show more workflows in the sidebar to see it).
  4. Once it finishes, you should see the release published under /releases. It won't be set as latest. It will also your SVN repo under branches/$VERSION and tags/$VERSION where $VERSION is the new stable release.

Illustrative Screenshots

Screenshot from 2023-03-14 18-58-20
The Update Changelog and upload Gutenberg plugin to WordPress.org plugin repo workflow for latest stable (point or not) releases.
Screenshot from 2023-03-14 19-39-52
The Update Changelog and upload Gutenberg plugin to WordPress.org plugin repo workflow for non-latest stable point-releases.
Screenshot from 2023-03-14 18-57-13
The "non-latest" stable point-releases are created as a branch in the SVN repo. It's also copied over to tags, too.

TODO

@@ -130,8 +145,8 @@ jobs:
- name: Replace the stable tag placeholder with the existing stable tag on the SVN repository
env:
STABLE_TAG_PLACEHOLDER: 'Stable tag: V\.V\.V'
STABLE_TAG: 'Stable tag: ${{ steps.get_previous_stable_version.outputs.stable_version }}'
run: sed -i "s/${STABLE_TAG_PLACEHOLDER}/${STABLE_TAG}/g" ./trunk/readme.txt
run: |
Copy link
Member Author

Choose a reason for hiding this comment

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

Before, STABLE_TAG was based on the value of steps.get_previous_stable_version.outputs.stable_version, which for me looked a bit confusing, given the get_previous_stable_version step -- we actually want the current latest version, and not the previous, and we can get that from the VERSION env variable, defined as an env variable for the job and passed as part of the payload for the release event.

env:
STABLE_TAG_PLACEHOLDER: 'Stable tag: V\.V\.V'
run: |
sed -i "s/$STABLE_TAG_PLACEHOLDER/Stable tag: $VERSION/g" ./branches/$VERSION/readme.txt
Copy link
Member Author

Choose a reason for hiding this comment

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

@fullofcaffeine fullofcaffeine changed the title [Github-Actions-Workflows][Plugin-Release] Allow shipping a point-release for a older stable branch [Github-Actions-Workflows][Plugin-Release] Allow shipping a point-release for an older "non-latest" stable branch Mar 15, 2023
@fullofcaffeine fullofcaffeine changed the title [Github-Actions-Workflows][Plugin-Release] Allow shipping a point-release for an older "non-latest" stable branch [Github-Actions-Workflows][Plugin-Release] Allow shipping a point-release for an older "non-latest" stable release Mar 15, 2023
@noahtallen
Copy link
Member

For this to work well, the GitHub draft release for this patch-release should NOT be marked as the latest release when it's published, or it will be considered the last release by the workflow and will replace trunk!*[0]

we can always revert the changes in the SVN repo manually.

This is my only major concern. While I definitely follow your reasoning, I also see it being a very easy step to miss, even for someone experienced with the workflow. And yet it could have big repercussions if it actually overwrites the trunk version in WordPress.org, because that impacts anyone installing the plugin on their own sites, not just us

I think at the very least, we need to avoid pushing to the SVN repo in this scenario, even if someone accidentally sets the latest release in GitHub. I imagine changing the latest release in GitHub is easier than reverting in SVN?

@fullofcaffeine
Copy link
Member Author

I think at the very least, we need to avoid pushing to the SVN repo in this scenario, even if someone accidentally sets the latest release in GitHub. I imagine changing the latest release in GitHub is easier than reverting in SVN?

Yeah, I'll see if I can come up with a condition that will avoid the publish event from triggering the upload action if the GB version being published is from an older branch. A simpler alternative might be to set it up so that the Set as the latest release is not checked by default for those releases, but I'm not sure if that's possible.

@ockham
Copy link
Contributor

ockham commented Mar 20, 2023

A simpler alternative might be to set it up so that the Set as the latest release is not checked by default for those releases, but I'm not sure if that's possible.

It seems like there's a make_latest field in GH's REST API to control this (see).


Edit: Oh, the docs say

Drafts and prereleases cannot be set as latest.

So maybe we cannot control it for a draft, and there's a "latest" checkbox that's preselected when people go to manually publish it? 😕

@ockham
Copy link
Contributor

ockham commented Mar 22, 2023

Looks like this needs a rebase to account for #45932 🙂

Revert changes I made in order to test end-to-end from a test fork.
@ockham ockham force-pushed the ship/older-stable-point-releases-as-branches branch from 321db3e to d685abb Compare March 22, 2023 14:06
@ockham
Copy link
Contributor

ockham commented Mar 22, 2023

Looks like this needs a rebase to account for #45932 🙂

Done. I made sure to preserve the commits, and updated the PR desc to point the instructions to the newly rebased first commit.

Comment on lines 218 to 230
- name: Commit the content changes
working-directory: ./branches
run: |
svn st | grep '^?' | awk '{print $2}' | xargs -r svn add
svn st | grep '^!' | awk '{print $2}' | xargs -r svn rm
svn commit -m "Committing version $VERSION" \
--no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD"

- name: Create the SVN tag
working-directory: ./branches
run: |
svn copy "$PLUGIN_REPO_URL/branches/$VERSION" "$PLUGIN_REPO_URL/tags/$VERSION" -m "Tagging version $VERSION" \
--no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD"
Copy link
Contributor

Choose a reason for hiding this comment

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

I know I had mentioned in our Slack convo that the tags should be created from the corresponding branches. However, what I meant was ideally to have a x.y branch (e.g. 15.4), which would be created at the time that 15.4.0 is released, and from which all point releases are created. (This would be to mimic the behavior we have here in the GB git repo, and also what WP Core is doing in its svn repo.)

Among other things, this would somewhat reflect in svn that e.g. 15.4.2 is based on 15.4.1, which in turn is based on 15.4.0, etc. However, the idea is also partly based on my ignorance of how branching and tagging works in svn.

Maybe we can get away without any branching at all? 🤔 Would it be possible to commit the release files straight to /tags/ (i.e. without committing them to /branches/)? (After all, for the actual plugin code, git is our source of truth, so we don't need to go out of our way to mimic the branches and tags in the GB git repo.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in 9dc4b39

@ockham
Copy link
Contributor

ockham commented Mar 22, 2023

I think at the very least, we need to avoid pushing to the SVN repo in this scenario, even if someone accidentally sets the latest release in GitHub. I imagine changing the latest release in GitHub is easier than reverting in SVN?

Yeah, I'll see if I can come up with a condition that will avoid the publish event from triggering the upload action if the GB version being published is from an older branch. A simpler alternative might be to set it up so that the Set as the latest release is not checked by default for those releases, but I'm not sure if that's possible.

Yeah, that's exactly what I had in mind -- I think we can de-risk this workflow quite a bit by making sure the pre-selected default is fine (unchecked in this case).

I've noticed that the create-release action is deprecated and unmaintained. We could consider replacing it by a few lines of GH API (octokit) code (written in JS!) using the github-script action. (I really hope that there's some field that will allow us to control the default value of that "latest" checkbox.)

@fullofcaffeine
Copy link
Member Author

fullofcaffeine commented Mar 22, 2023 via email

@fullofcaffeine
Copy link
Member Author

fullofcaffeine commented Mar 22, 2023 via email

@fullofcaffeine
Copy link
Member Author

fullofcaffeine commented Mar 22, 2023 via email

@fullofcaffeine
Copy link
Member Author

fullofcaffeine commented Mar 22, 2023 via email

@fullofcaffeine
Copy link
Member Author

fullofcaffeine commented Mar 22, 2023 via email

@fullofcaffeine
Copy link
Member Author

fullofcaffeine commented Mar 22, 2023 via email

fullofcaffeine and others added 3 commits April 7, 2023 10:45
Co-authored-by: Bernie Reiter <ockham@raz.or.at>
Co-authored-by: Bernie Reiter <ockham@raz.or.at>
@noahtallen noahtallen requested a review from gziolo May 9, 2023 18:22
… timeout issues while testing"

This reverts commit da46aba.
This commit significantly optimizes the process of adding a new tag to the SVN repository in our GitHub Workflow.

Previously, our process involved checking out the entire tags directory from the SVN repository, which led to increased execution time and failure points when the tags directory was filled with numerous versions.

We've resolved this issue by leveraging the svn import command, which allows us to directly add a new directory to the tags directory without checking out the existing directories first. This results in faster and more reliable workflow execution, particularly when dealing with repositories that have accumulated many tagged versions.

The changes made include:

    Removing the step to checkout Gutenberg tags from the WP.org plugin repository.
    Adding a new step that uses the svn import command to directly add a new version directory to the SVN repository. This is achieved without the need to checkout all existing directories under tags/.
    Removing the step to checkout the new Gutenberg tag as it's not needed anymore.
This commit enhances the conditional checks within the 'upload' and 'upload-tag' jobs in our GitHub Actions workflows.

Previously, the jobs were executed based solely on the 'prerelease' flag of the release. However, there could be situations where this flag is accidentally set to 'false' for a Release Candidate (RC).

To avoid such mishaps, the conditions have been extended to check for the '-rc' suffix in the version string as well. This ensures that even if the 'prerelease' flag is incorrectly marked as 'false', the 'upload' and 'upload-tag' jobs are still skipped for RCs, thus preventing any unintended release of RC builds.
This makes sure we don't upload RCs as trunk or tag even if the deployer accidentally unchecks the "Set as prerelease" flag.
@fullofcaffeine fullofcaffeine force-pushed the ship/older-stable-point-releases-as-branches branch from aebc503 to 472262e Compare May 26, 2023 02:10
Effectively reverts changes in 014e2c6.
Reverts changes from 489aa70. If further testing is needed, revert the changes here again.
Copy link
Contributor

@ockham ockham left a comment

Choose a reason for hiding this comment

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

Okay. Based on all the testing we've done, plus the safeguards you've added, LGTM 🤞😮‍💨🚢

Comment on lines +38 to +52
# Determines if the first version string is greater than the second version string.
#
# Params:
# $1 - The first version string to compare, which may have an optional leading "v".
# $2 - The second version string to compare, which may have an optional leading "v".
#
# Return values:
# 0 - The first version string is greater than the second version string.
# 1 - The first version string is less than or equal to the second version string.
is_first_version_greater_than_second() {
v1=${1#v}
v2=${2#v}
dpkg --compare-versions "$v1" gt "$v2"
return $?
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Definitely not for this PR, but in a follow-up, can we maybe replace this with the semver npm? I'm already using it in a few places in the build-plugin workflow (e.g.) to compute version numbers, and it also supports comparison

semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true

(and cleanup: semver.clean(' =v1.2.3 ') // '1.2.3').

(dpkg is a Debian/Ubuntu tool IIRC, and I've tried to avoid bash-isms and other dependencies as much as possible in order to make local testing of individual steps from workflows at least a bit easier across platforms -- including MacOS.)

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a good point. I'll take note of that for a follow-up 👍🏻

@ockham
Copy link
Contributor

ockham commented Jun 7, 2023

Let's just make sure to announce this properly, e.g. in #core-editor. Thinking of something like:

@fullofcaffeine and I would like to land a PR that adds a new feature to the Gutenberg release workflow (in GitHub Actions), which will enable us to publish a point release for a previous version series even if a new stable release has already been published. E.g. if the current Gutenberg version is 15.9.1, and we discover a serious bug in 15.8.1, Marcelo’s change will allow us to publish a 15.8.2 release with a bugfix — somewhat akin to Core. (In this example, 15.9.1 will continue to be marked as 'latest' release, so no WordPress installs running it will be at risk of downgrading.)

The PR contains a number of safeguards and has undergone exhaustive testing, but due to the way that GHA workflows work, and due to the many parts involved, there’s still a risk that we missed some edge-case bug. For this reason, we’ll make sure that at least one of us will be around when the next Gutenberg RC and stable versions are published.

Am I missing anything important? 🤔

Maybe one of us should volunteer to run the first GB release after landing this 🤔
Speaking of landing this: We should probably do that after a stable release is out (and before a new series is started by an RC). Let's maybe consult with @priethor on when would be a good time (also considering WP 6.3).

@fullofcaffeine
Copy link
Member Author

@ockham Sounds good! @priethor 👋🏻 When would be a good day to release this? At first glance, I'm thinking of scheduling to the next week (19th-23rd June, any of these days), but I'm not sure what's the 6.3 status/timeline. Thanks!

@tellthemachines
Copy link
Contributor

The next Gutenberg release (16.1) will be the last before 6.3 Beta 1, and as editor tech leads, either @ramonjd or myself will likely be running it. If this isn't an urgent change, it might be safer to aim for 16.2 so that there's no risk of disruption to 6.3 Beta.

@ockham
Copy link
Contributor

ockham commented Jun 13, 2023

Sounds good, thank you @tellthemachines. So if I'm not mistaken:

  • 16.0 is due tomorrow (June 14); which means that
  • 16.1 is due on June 28, and
  • 16.2 is due on July 12 (with an RC1 on July 5th).

@fullofcaffeine How about we merge this on July 5th and also take care of publishing 16.2 RC1 right afterwards?

@fullofcaffeine
Copy link
Member Author

@fullofcaffeine How about we merge this on July 5th and also take care of publishing 16.2 RC1 right afterwards?

Sounds like a good plan! 👍🏻

Removed in WordPress@014e2c6.

I accidentally removed it instead of commenting out, so I forgot to reactivate it.

The problem was that due to the amount of changes later, I couldn't just revert this commit.
@fullofcaffeine fullofcaffeine merged commit 68fa80a into WordPress:trunk Jul 5, 2023
48 checks passed
@github-actions github-actions bot added this to the Gutenberg 16.2 milestone Jul 5, 2023
fullofcaffeine added a commit that referenced this pull request Jul 7, 2023
…ease for an older stable release (#49082)

* Allow point-releases for release branches that are not the latest anymore

And other minor improvements

* Revert debug changes

Revert changes I made in order to test end-to-end from a test fork.

* Limit runs to `release/` branches

Co-authored-by: Bernie Reiter <ockham@raz.or.at>

* Fix changelog directory interpolation

Co-authored-by: Bernie Reiter <ockham@raz.or.at>

* Re-add debug changes for further testing

* Create only the tag when releasing an older point release, do not create a branch anymore

* Implement guard against accidental trunk release of older point releases

This refactors the upload zip workflow and add some version arithmetic to make sure the right version is uploaded depending:
- what is the current version set as latest -- this signals that a trunk release could be imminent, but is not enough to define it
- what is the current version in the WP core repo (real latest released version) -- this is compared with the published version and if it's greater than this version + the version was set as latest in GH, then it is a trunk release
- If the conditions above are false, then it's a tag release.

See the source for more details.

* Attempt to fix "fetch" already defined error when running the script in the GH actions env

* Simplify by not using node-fetch, or it will require installing the npm

* GH requires an user-agent

* Improve var name and comments

* Define func to set the output of the "compute-should-update-trunk" job and improve its name

* The core object should already be available as part of the github-scripts package

* Rely only in the github ref from the published release and not the latest tag, restructure the workflow to make it easier to debug and simplify it by using shell commands/script instead of JS

* Simplify further by moving the fetch core repo job to a step inside compute_should_update_trunk

* Fix/improve step/job ids

* Fix typo

* Formatting fixes

Auto-format with the RedHat YAML extension in vscode.

* Add missing outputs and a couple of other fixes

* A couple more fixes and a simplification of the compute_latest_version step

* Mock the build of the gutenberg.zip for debugging purposes, this commit should be reverted before merging!

* Fix a couple of step names

* Re-add prelease attribute, was accidentally commented out

* Debug commit, please revert: mock the version number in the version repo

* Fix changelog fetching when uploading the SVN tag

* Mock SVN version to 16.1.0

* Make the svn commit command verbose in order to debug network timeout issues while testing

* Revert "Make the svn commit command verbose in order to debug network timeout issues while testing"

This reverts commit da46aba.

* Optimize SVN tag addition in GitHub workflow

This commit significantly optimizes the process of adding a new tag to the SVN repository in our GitHub Workflow.

Previously, our process involved checking out the entire tags directory from the SVN repository, which led to increased execution time and failure points when the tags directory was filled with numerous versions.

We've resolved this issue by leveraging the svn import command, which allows us to directly add a new directory to the tags directory without checking out the existing directories first. This results in faster and more reliable workflow execution, particularly when dealing with repositories that have accumulated many tagged versions.

The changes made include:

    Removing the step to checkout Gutenberg tags from the WP.org plugin repository.
    Adding a new step that uses the svn import command to directly add a new version directory to the SVN repository. This is achieved without the need to checkout all existing directories under tags/.
    Removing the step to checkout the new Gutenberg tag as it's not needed anymore.

* Enhance safety checks in workflow to skip upload jobs for RC builds

This commit enhances the conditional checks within the 'upload' and 'upload-tag' jobs in our GitHub Actions workflows.

Previously, the jobs were executed based solely on the 'prerelease' flag of the release. However, there could be situations where this flag is accidentally set to 'false' for a Release Candidate (RC).

To avoid such mishaps, the conditions have been extended to check for the '-rc' suffix in the version string as well. This ensures that even if the 'prerelease' flag is incorrectly marked as 'false', the 'upload' and 'upload-tag' jobs are still skipped for RCs, thus preventing any unintended release of RC builds.

* Revert "Enhance safety checks in workflow to skip upload jobs for RC builds"

This reverts commit eae536a.

* Skip upload jobs if release is an RC by checking the ref for a rc suffix

This makes sure we don't upload RCs as trunk or tag even if the deployer accidentally unchecks the "Set as prerelease" flag.

* Revert build plugin mocking logic

Effectively reverts changes in 014e2c6.

* Revert initial dev/debug changes

Reverts changes from 489aa70. If further testing is needed, revert the changes here again.

* Revert WP SVN repo version mock

Revert changes from fe8b33c.

* Add back if conditions that were accidentally removed

Removed in 014e2c6.

I accidentally removed it instead of commenting out, so I forgot to reactivate it.

The problem was that due to the amount of changes later, I couldn't just revert this commit.

---------

Co-authored-by: Bernie Reiter <ockham@raz.or.at>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GitHub Actions Pull requests that update GitHub Actions code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants