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

Add automated release workflows and update releasing guide #269

Merged
merged 3 commits into from
Mar 12, 2022

Conversation

mattwynne
Copy link
Member

🤔 What's changed?

  • Added GitHub Actions workflows for automating releases
  • Updated RELEASING.md guide

⚡️ What's your motivation?

Automate releases! 🎉 No more need to use the big docker image! 🎉

🏷️ What kind of change is this?

  • 🏦 Refactoring/debt (improvement to code design or tooling without changing behaviour)

📋 Checklist:

  • I agree to respect and uphold the Cucumber Community Code of Conduct
  • I've changed the behaviour of the code
    • I have added/updated tests to cover my changes.
  • My change requires a change to the documentation.
    • I have updated the documentation accordingly.
  • Users should know about my change
    • I have added an entry to the "Unreleased" section of the CHANGELOG, linking to this pull request.

@mattwynne mattwynne changed the title Add automated release workflows and update releaseing guide Add automated release workflows and update releasing guide Feb 17, 2022
@mattwynne
Copy link
Member Author

@gaeljw this should be considered a "first draft" for the workflow.

I've set up all the repo settings - protected branch rules, and a Release environment with the secrets in it.

What I'm not so sure about it the right maven goals to call. Similar to this PR I need your attention and feedback to help get that right.

@gaeljw
Copy link
Member

gaeljw commented Feb 18, 2022

First, very cool to see this automated workflows appearing in Cucumber repos :)


The thing is cucumber-scala is not built with Maven but with sbt as you can see in the previous Makefile release command: sbt "release cross with-defaults".
For completeness this is actually sbt with the sbt-release, sbt-pgp and sbt-sonatype plugins.


One thing to note is that the sbt "release cross with-defaults" will by default release without asking for a version number (it will take the x.y.z-SNAPSHOT version defined in version.sbt and release x.y.z).
For our use case, we should define it explicitly:

I suppose first option would be enough?


For reference, here is an example of a GitHub automated workflow for releasing a personal project: https://github.com/gaeljw/typetrees/blob/main/.github/workflows/release.yml (ignore the gpg step which for some reason I don't actually remember was set a bit differently in cucumber-scala and uses a file gpg.sh in the project itself).


From what I understand, we should build a GitHub action cucumber/action-publish-sbt maybe? (I can help with that of course).

java-version: "11"
cache: "maven"

- uses: cucumber/action-publish-mvn@v1.0.0
Copy link
Member

Choose a reason for hiding this comment

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

This will probably not work, should we define a cucumber/action-publish-sbt instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it sounds like it. If you can help with that it would be great. I'll set up the repo next week.

Copy link
Member

Choose a reason for hiding this comment

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

Sure, as soon as you have the repo I can work on it.

Not sure how to test without actually doing any release but we'll see 😅
I have few Renovate open PRs that can serve as an excuse for doing a patch release anyway.

Copy link
Member Author

@mattwynne mattwynne Feb 22, 2022

Choose a reason for hiding this comment

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

OK I have added the repo and made you an admin.

https://github.com/cucumber/action-publish-sbt

We need to limit the access to these github actions repos as they're a potential vector for supply-chain attacks, so we don't give write access to the general commiters team for these repos.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just for my understanding, we're using sbt instead of mvn for build automation, but are we still publishing to sonatype in the end? I'm just trying to get my head around the pieces of the ecosystem.

Copy link
Member Author

Choose a reason for hiding this comment

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

I also think it's valid to do a patch release just to test the automation.

Copy link
Member Author

Choose a reason for hiding this comment

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

We need to limit the access to these github actions repos as they're a potential vector for supply-chain attacks, so we don't give write access to the general commiters team for these repos.

Also, assuming we set up CI on the main branch to run a test publish, it could be possible to leak those secrets so again we need to lock down who can push to main here.

Copy link
Member

Choose a reason for hiding this comment

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

Cool, I'll have a look in the coming days.

No issue with limiting access to the action repo, perfectly make sense.

Just for my understanding, we're using sbt instead of mvn for build automation, but are we still publishing to sonatype in the end? I'm just trying to get my head around the pieces of the ecosystem.

Absolutely. sbt is very similar to Maven in the sense that it works for the JVM ecosystem and publish to Sonatype. It's juste way more fitted for Scala projects.

For the record, the artifact on Maven central: https://mvnrepository.com/artifact/io.cucumber/cucumber-scala

Copy link
Member

Choose a reason for hiding this comment

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

@mattwynne I have a doubt: is the project version supposed to be x.y.z-SNAPSHOT before pushing to the branch release/x.y.z? Or should the Action retrieve branch name and make a release with the version given in the branch name?

2nd option seems more natural to me but I don't see anything that does something similar in the Maven action or Maven project

Copy link
Member Author

Choose a reason for hiding this comment

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

Good question.

The "modern" process is outlined in https://github.com/cucumber/.github/blob/main/RELEASING.md and there are examples in, say https://github.com/cucumber/tag-expressions/tree/main/.github/workflows

Right now that process is to manually modify the CHANGELOG with the next release number, and manually update the relevant package descriptor, before pushing the commit to a release/* branch. So the existing maven action just releases whatever it sees in pom.xml.

In fact using the version number in the release branch is just a convention, you could call it release/foo and it would still work. Nothing looks at the branch name currently.

The https://github.com/cucumber/action-create-github-release action does read the version number from the CHANGELOG, and potentially we could do the same to get the number needed for the sbt release. In fact we have a special GitHub action for that: https://github.com/cucumber/action-get-versions which I was tinkering with for automating more of this, but I hadn't got around to it yet.

@gaeljw
Copy link
Member

gaeljw commented Mar 12, 2022

I added a commit to use the just-released cuucmber sbt action v1.0.0 and also updated the documentation.

I will merge this PR as well as pending PR opened by Renovate to test the process and release a patch version of the library.

@gaeljw gaeljw merged commit 748e8ce into main Mar 12, 2022
@gaeljw gaeljw deleted the automate-release branch March 12, 2022 17:00
@gaeljw
Copy link
Member

gaeljw commented Mar 12, 2022

@mattwynne after some small bugfixes it worked 🎊

Few comments:

  • I merged the sbt and github release workflow because I don't think it makes sense to release on Github if the sbt release failed
  • In case the release workflow fails, the branch release/vx.y.z cannot be reused (protected) and thus forces to increment version even though no version x.y.z exists yet. It's a good protection but a bit too much IMHO. Though I admit the release workflow should not fail often in the future 🤞
  • For the same reason (protected branch), I had to tune the sbt release plugin because it usually is responsible for doing the git tag, updating the next version and pushing but it cannot do any of that with the current process. I mean it's fine for this project but I think you will hit similar issues with other Java/Maven projects.
  • There's still some manual actions (updating version, changelog and documentation) that could be part of the automated release IMHO, I'll give more thought about it. I don't want to drift too much from the recommended Cucumber process though.
  • I guess it's not possible to delete the release/vx.y.z branches but they tend to pollute the repository IMHO

@gaeljw gaeljw mentioned this pull request Mar 13, 2022
@mattwynne
Copy link
Member Author

mattwynne commented Mar 16, 2022

Hey @gaeljw! (sorry for the hiatus, I've been ill but I seem to be recovering now)

That's great you got it working!

@mattwynne after some small bugfixes it worked 🎊

Few comments:

  • I merged the sbt and github release workflow because I don't think it makes sense to release on Github if the sbt release failed

Yes. @aurelien-reeves and I went back and forth on this. We settled on having separate workflows because GitHub, at the time, did not allow you to re-run individual failed jobs, only workflows. I believe they've just fixed that, so a single workflow probably makes more sense now.

  • In case the release workflow fails, the branch release/vx.y.z cannot be reused (protected) and thus forces to increment version even though no version x.y.z exists yet. It's a good protection but a bit too much IMHO. Though I admit the release workflow should not fail often in the future 🤞

Yes, my view is it's probably a good idea just to do a new patch release if something goes wrong with the release infrastructure. If that happens it will be easier to tell what's happened retrospectively, especially if it takes a few goes to fix something.

  • For the same reason (protected branch), I had to tune the sbt release plugin because it usually is responsible for doing the git tag, updating the next version and pushing but it cannot do any of that with the current process. I mean it's fine for this project but I think you will hit similar issues with other Java/Maven projects.

  • There's still some manual actions (updating version, changelog and documentation) that could be part of the automated release IMHO, I'll give more thought about it. I don't want to drift too much from the recommended Cucumber process though.

@mpkorstanje and I paired yesterday on the release automation for cucumber-parent, which we drive from a Makefile and we kept something similar there which uses a maven plugin (I think this one?) to modify the version in the POM, remove -SNAPSHOT etc.

I don't think there's any harm in running something which tags the commit - the GitHub release action will re-tag the same commit but that's no problem IMO.

So we could look at this as a later optimisation. We're also looking at automatically updating the changlog.

The process is evolving all the time, and there's definitely more stuff we can streamline. I think cucumber-parent's make release is probably closest to @davidjgoss's vision of a "one click" release process, and I hope we can take something from these JVM projects and bring it back for others to benefit from.

  • I guess it's not possible to delete the release/vx.y.z branches but they tend to pollute the repository IMHO

I think you can safely delete these branches once the release has completed. Maybe we can even automate that.

@gaeljw
Copy link
Member

gaeljw commented Mar 20, 2022

Hope you're doing better @mattwynne 🙂

It seems I actually don't have rights on the protected branches. I can push to them but cannot delete them 🤔

I'll give a look to the work done on cucumber-parent and keep you posted if I have ideas.

Thanks

@mpkorstanje
Copy link
Contributor

. I can push to them but cannot delete them

It's in the branch protection options somewhere. Deleting is not enabled by default but can be for anyone with push access.

@mpkorstanje
Copy link
Contributor

Yes, my view is it's probably a good idea just to do a new patch release if something goes wrong with the release infrastructure. If that happens it will be easier to tell what's happened retrospectively, especially if it takes a few goes to fix something.

Been doing manual clean up while setting up. For intermittent failures this is nothing more then deleting a release branch and pushing the tag to it again.

For more structural problems rolling back a few commits is also relatively easy. Delete the tag, Delete the release branch, reset main to the commit before release.

@davidjgoss
Copy link

@davidjgoss's vision of a "one click" release process

I don't know about "vision" @mattwynne :) and one click probably isn't realistic given our constraints but I think "can do with a few operations on github.com" is a good north star. Running a workflow on main and then creating a release branch would definitely fit that bill.

@mattwynne
Copy link
Member Author

@davidjgoss's vision of a "one click" release process

I don't know about "vision" @mattwynne :) and one click probably isn't realistic given our constraints but I think "can do with a few operations on github.com" is a good north star. Running a workflow on main and then creating a release branch would definitely fit that bill.

The thing I've been struggling with this idea is that, as far as I know, it's not possible to trigger a workflow to run as you (even if you use a workflow_dispatch event, which would be ideal for this) so I think the thing that pushes to the protected release branch can't be done from a GitHub Action 🤔

@mattwynne
Copy link
Member Author

. I can push to them but cannot delete them

It's in the branch protection options somewhere. Deleting is not enabled by default but can be for anyone with push access.

Indeed:
Screenshot 2022-03-22 at 10 30 03 PM

Try again @gaeljw?

@davidjgoss
Copy link

@mattwynne yeah I more meant like:

  1. Run workflow which creates the Release $next_release commit on main
  2. Create a release branch from main via the GitHub UI like normal (below)
Screen.Recording.2022-03-23.at.07.59.53.mov

@gaeljw
Copy link
Member

gaeljw commented Mar 23, 2022

Try again @gaeljw?

Better, thanks @mattwynne

@gaeljw
Copy link
Member

gaeljw commented Mar 23, 2022

I do like the idea of running part of the release workflow on main branch and only use the protected branches for the actual sensitive action like releasing the artifact to Sonatype.

@aslakhellesoy aslakhellesoy mentioned this pull request Mar 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants