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/workflows: Add workflow for supported automated releases #1106

Merged
merged 1 commit into from
Sep 6, 2023

Conversation

nywilken
Copy link
Contributor

@nywilken nywilken commented Aug 15, 2023

This change builds on the documented release process to add a workflow for automated releases using GoReleaser.
Upon merging this change, you will be able to trigger a new CLI release by pushing a VERSION tag to the repository.
The supported tag formats are vX.Y.Z and vX.Y.Z-* (pre-releases). By default goreleaser will use the tag
to determine if the triggered release is an official release or a pre-release.

Closes: #1103

Additional changes for supporting automated releases:

  • The version command was updated to support variable injection via ldflags. This was done to allow GoReleaser to set the version of the CLI to the tagged version; goreleaser drops the v prefix by default setting
    the version to X.Y.Z

  • Added GPG signing action to support GPG signing the goreleaser generated checksum file. The workflow requires the following secrets be created in the upstream repository secrets.GPG_PRIVATE_KEY and secrets.PASSPHRASE. Instructions on the expected values for these secrets can be found here

  • Updated the RELEASE.md document with details for triggering an automated release on GitHub. The manual instructions were left mostly unchanged for describing the process, which is a nice to have in case GitHub actions are experiencing issues.

  • Added a .release directory for storing release helper files like .release/header.md, which is used by goreleaser when generating release notes.

  • Release archives for exercism_windows_64bit.zip and exercism_windows_32bit.zip are now generated and published at release time. The release archives are also included in the checksum file.

  • The generated release archives now contain the shell/** files. They were being skipped in previous releases.

@github-actions
Copy link

Hello. Thanks for opening a PR on Exercism. We are currently in a phase of our journey where we have paused community contributions to allow us to take a breather and redesign our community model. You can learn more in this blog post. As such, all issues and PRs in this repository are being automatically closed.

That doesn't mean we're not interested in your ideas, or that if you're stuck on something we don't want to help. The best place to discuss things is with our community on the Exercism Community Forum. You can use this link to copy this into a new topic there.


Note: If this PR has been pre-approved, please link back to this PR on the forum thread and a maintainer or staff member will reopen it.

@github-actions github-actions bot closed this Aug 15, 2023
@nywilken nywilken mentioned this pull request Aug 16, 2023
@ErikSchierboom
Copy link
Member

How should the release notes be grouped, filtered, and sorted to ensure descriptive release notes?

I would be perfectly happy with just a regular list, not grouping or filtering or anything.

The changelog functionality for goreleaser is currently set to use git log for generating release notes to attach to the GitHub release. A test release can be found
at nywilken/exercism-cli. The git log delta is due to this being the first release.

Are releases created as drafts? If so, I'm happy for something like what you have to be present, as we can then tweak the text before publishing. That said, every release note starts with:

To install, follow the interactive installation instructions at https://exercism.io/cli-walkthrough
---

Is there an option for using github-native as the changelog generation algorithm?
This option will generate a changelog entry for each merged PR. The PRs can be grouped by labels (enhancement, bug, breaking changing, etc...) and controlled by GitHub's native release note generation alogrithm. An example of the generated changelog is here and the controlling configuration is here. Refer to GitHub docs for full config options.

We could do that, we'd just need to be diligent about it. Did you check the existing labels we use https://github.com/exercism/cli/labels ?

Is it okay for the automated release to complete before the installer is created?

The installer isn't updated, but retrieves the latest release automatically.

In the current release process there is step for uploading copies of the Windows files for use by the Exercism Windows installer. But it is not clear why this is done before uploading the remaining release assets.

What do you mean that is it done before uploading the remaining release assets? Aren't they uploaded in goreleaser --clean?

Is there a reason why there are no labels being used for issues and pull-requests?

It requires more effort, that's basically it. I'm not opposed to them being used, but it is a slight additional maintenance burden and we don't really have a maintainer.

@ErikSchierboom
Copy link
Member

I'll review the code once the above questions/comments have been handled (they might influence things).

@nywilken
Copy link
Contributor Author

@ErikSchierboom thanks for answering my questions I have what I need to continue pushing the ball forward.
I've responded to your questions below.

Are releases created as drafts? If so, I'm happy for something like what you have to be present, as we can then tweak the text before publishing.

The configuration in my PR will automatically publish the release as an official release. But tbh if it's in the workflow to modify the release-notes a draft sounds like a great idea. I'll update the PR to generate a draft.

My initial thinking was to fully automate the release with release notes to a point where no manual intervention is needed, if possible.

In the current release process there is step for uploading copies of the Windows files for use by the Exercism Windows installer.
What do you mean that is it done before uploading the remaining release assets? Aren't they uploaded in goreleaser --clean?

Ah yes, you are correct they are uploaded by goreleaser --clean. I thought they were being uploaded manually after running goreleaser --skip-publish --snapshot --clean.

I see now that the installer archives require a different filename from those generated by goreleaser so that is why they are uploaded separately. I will adjust the goreleaser configuration to also generate and publish exercism-windows-64bit.zip and exercism-windows-32bit.zip as part of the release.

It requires more effort, that's basically it. I'm not opposed to them being used, but it is a slight additional maintenance burden and we don't really have a maintainer. We could do that, we'd just need to be diligent about it.

Regarding the use of labels I completely understand the overhead and they are not needed. The use of labels can help when generating release notes if using GitHub to generate the release notes but it is not a requirement.

Did you check the existing labels we use https://github.com/exercism/cli/labels ?

I have not but will took a quick peek.

I would be perfectly happy with just a regular list, not grouping or filtering or anything.

Rolling with the git log option is a good way to go.

@nywilken
Copy link
Contributor Author

nywilken commented Aug 23, 2023

Quick update - I re-rolled the proposed changes to account your feedback. I have a new example release available for you to reference https://github.com/nywilken/exercism-cli/releases/tag/v3.2.1-nywilkenrc3

The new release has the following changes:

  1. A header file in a hidden directory .release/header.md that is used by goreleaser to automatically add the install instructions to the top of the generated release notes.
  2. Release archives for exercism_windows_64bit.zip and exercism_windows_32bit.zip are now generated and published at release time. The release archives are also included in the checksum file.
  3. The generated release archives now contain the shell/** files. They were being skipped in previous releases.
  4. I added back the draft directive to create draft releases. I published the release so that you can preview it.

Let me know if you have any additional thoughts or questions about the proposed changes.

@nywilken nywilken force-pushed the release-workflow branch 2 times, most recently from 2bcf142 to e982e40 Compare August 23, 2023 15:57
@ErikSchierboom
Copy link
Member

Sorry for the slow reviewing process, I'm slightly flooded with jobs at the moment. I will get back to it.

@nywilken
Copy link
Contributor Author

Sorry for the slow reviewing process, I'm slightly flooded with jobs at the moment. I will get back to it.

@ErikSchierboom no worries. I understand. There's no rush. Please take the time you need. I used to help with this project and would like to help maintain it again if possible. So hoping that the release PR can help simplify some of the work for future releases.

runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
Copy link
Member

Choose a reason for hiding this comment

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

Could you pin the actions to SHAs? It's a security measure. See https://exercism.org/docs/building/github/gha-best-practices#h-pin-actions-to-shas for more information


jobs:
goreleaser:
runs-on: ubuntu-latest
Copy link
Member

Choose a reason for hiding this comment

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

Could you pin the test runner to a specific version? See https://exercism.org/docs/building/github/gha-best-practices#h-pin-actions-to-shas

.goreleaser.yml Outdated
ldflags:
- '-s -w -X {{ .ModulePath }}/cmd.Version={{.Version}}' # sets binary version to match tag without 'v' prefix
Copy link
Member

Choose a reason for hiding this comment

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

This is to replace the version with the tag, right? I'm not opposed to this change, but I also think there is some value in having the version directly defined in the code. With the current setup, there could be a disconnect between the tag version and the version in the file, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is to replace the version with the tag, right? I'm not opposed to this change, but I also think there is some value in having the version directly defined in the code. With the current setup, there could be a disconnect between the tag version and the version in the file, right?

Yes, the version is injected at build time. I agree that the version should be properly set within cmd/version.go before triggering the release. Seeing as bumping the version and CHANGELOG.md is part of the release process I figured the person releasing would bump the version before triggering the release.

That said, this does add a little disconnect between the tag version and the version file if the release workflow is not followed directly. Which can also be a crutch if the tag version is correct but the version.go file is not.

If you this adds possible confusion or room for error we can drop the change. I thought locally (manual release) would be an issue but it looks like the process is to create the tag before running goreleaser, which will result in the correct version being injected locally as well.

# Create a new tag on the main branch and push it
git tag -a "${TAG_NAME}" -m "Trying out GoReleaser"
git push origin "${TAG_NAME}"

# Build and release
goreleaser --clean

Copy link
Member

Choose a reason for hiding this comment

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

If you this adds possible confusion or room for error we can drop the change.

I think I would prefer that. We can always add it later. Ideally we'd be able to automate as much of the version bumping too at some point.

Copy link
Contributor Author

@nywilken nywilken Sep 1, 2023

Choose a reason for hiding this comment

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

Yeah good call. The change has been removed. I rebased and squashed commits a bit but you should be able to see the last commit where I revert

@nywilken
Copy link
Contributor Author

nywilken commented Sep 1, 2023

@ErikSchierboom thanks for the time and help with the PR. I re-rolled to account for the feedback. Feel free to review at your convenience.

I’m heading out for the long weekend so my responses will be delayed. Cheers!

Copy link
Member

@ErikSchierboom ErikSchierboom left a comment

Choose a reason for hiding this comment

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

One last tiny comment and one question: the workflow creates a draft release, correct?

RELEASE.md Outdated
@@ -46,12 +46,6 @@ git push origin "${TAG_NAME}"
# Build and release
goreleaser --clean
Copy link
Member

Choose a reason for hiding this comment

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

I think this line should no longer be a part of the instructions, correct? You could instead refer to the workflow that automatically runs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I removed the steps.

The current release documentation reads well if I simply remove this step so I don't think any additional changes are needed.

@nywilken
Copy link
Contributor Author

nywilken commented Sep 6, 2023

One last tiny comment and one question: the workflow creates a draft release, correct?

You are correct. My original commit was set to auto-publish the release but I updated .goreleaser.yml#L68 to create a draft after your initial feedback.

@nywilken
Copy link
Contributor Author

nywilken commented Sep 6, 2023

@ErikSchierboom this is ready for review. Please let me know if you have any questions or if you have any additional feedback.

Note: I can rebase and squash when ready to merge. I left all the commits as single entries for review purposes.

To summarize the change, upon pushing a semver formatted tag to the repository GitHub will trigger the release workflow to create a draft release matching the pushed version tag.

The draft release will contain all the previously released binaries along with two Windows binaries required by the installer. The generated checksum file will also containing SHA256SUM entries for the installer binaries, as they are now created by goreleaser.

The draft release will also contain generated release-notes that include the standard install walk-through header along with a bulleted list of git log entries for all changes that went into the release.

Lastly, before using this action the following secrets need to be added to the repository: secrets.GPG_PRIVATE_KEY and secrets.GPG_PASSPHRASE. Instructions on the expected values for these secrets can be found here

@nywilken nywilken force-pushed the release-workflow branch 2 times, most recently from d4e7995 to 7159a7d Compare September 6, 2023 10:49
Copy link
Member

@ErikSchierboom ErikSchierboom left a comment

Choose a reason for hiding this comment

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

One tiny comment

This change introduces a GitHub action workflow for publishing release
artifacts generated by goreleaser when a new tag is pushed.

* Add install walk-through to release notes header
A markdown file under a hidden release directory was added for use
with the gorleaser configuration for prepending a static header to the goreleaser generated
changelog.

* Update goreleaser configuration to generate installer archives
The Exercism installer requires the Windows archives to be
named slightly differently. In order to generate the archives as part
of the release process goreleaser has been split into two builds:
release-build and installer-build. The two builds are then archived
separately using the name_template configuration to generate the
properly named zip files. All generated archives are included in the final
release checksum.

* release.md: Updates release documentation to reflect the steps used by
  the automated pipeline
Copy link
Member

@ErikSchierboom ErikSchierboom left a comment

Choose a reason for hiding this comment

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

Stellar work. Can't wait to benefit from it the next release we do. Thanks for being patient with me

@ErikSchierboom ErikSchierboom merged commit 0fcf8c2 into exercism:main Sep 6, 2023
@ErikSchierboom
Copy link
Member

@nywilken I've just done the first release and it worked really well (I had to handle some GPG key shenanigans, but that's not on you): https://github.com/exercism/cli/actions/runs/7912951304/job/21600762816

The only thing that is not yet working is the homebrew part, which we discuss here: #1121 (comment)

And the draft release name was exercism-v3.3.0 runner. Where does the " runner" suffix come from?

@nywilken
Copy link
Contributor Author

nywilken commented Feb 15, 2024

@nywilken I've just done the first release and it worked really well (I had to handle some GPG key shenanigans, but that's not on you): https://github.com/exercism/cli/actions/runs/7912951304/job/21600762816

Sweet, thanks for that info. I’m glad you found it to work well for you.

And the draft release name was exercism-v3.3.0 runner. Where does the " runner" suffix come from?

Ah I didn’t notice this in the .goreleaser file but in the release name there looks to be a env.user suffix, which might be where runner is coming from.

Trying removing that from the line below 👇

name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}"

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.

Automate releases
2 participants