-
Notifications
You must be signed in to change notification settings - Fork 854
Add Release github action #6434
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # Workflow README.md | ||
| ## Automated Release | ||
|
|
||
| The workflow in the action_release.yml automates the process of creating a new GitHub Release whenever a version tag is pushed to the repository. It uses a series of community actions to handle code checkout, release note generation, and release creation. | ||
|
|
||
| It also allows for a manual creation of the release from the GitHub Actions page of the repository. | ||
|
|
||
| This workflow heavily leveraged the [release](https://github.com/containers/podman/blob/main/.github/workflows/release.yml) workflow in Podman. This README.md was | ||
| initially generated by Gemini, and then gently massaged. | ||
|
|
||
| ## 🚀 Workflow Purpose | ||
|
|
||
| The `action_release.yml` file defines a job that automatically: | ||
|
|
||
| 1. Checks out the code corresponding to the pushed tag. | ||
| 2. Generates structured release notes by analyzing merged Pull Requests between the previous tag and the new tag. | ||
| 3. Creates an official GitHub Release using the newly generated notes as the release description. | ||
|
|
||
| ## ⚙️ How to Use It | ||
|
|
||
| This workflow is **event-driven**, meaning you do not need to manually trigger it from the GitHub Actions tab. It is triggered by pushing a new Git tag. | ||
|
|
||
| It can also be triggered "by hand" if so desired. | ||
|
|
||
| ### Triggering the Release | ||
| #### Automatic Triggering | ||
| To run the workflow and create a new release, follow these steps in your local repository: | ||
|
|
||
| 1. **Create a New Tag:** Use the `git tag` command to create an annotated tag for your new version (e.g., `v1.2.3`). | ||
|
|
||
| ```bash | ||
| git tag -a v1.2.3 -m "Release version 1.2.3" | ||
| ``` | ||
|
|
||
| 2. **Push the Tag:** Push the tag to your GitHub repository. | ||
|
|
||
| ```bash | ||
| git push upstream v1.2.3 | ||
| ``` | ||
|
|
||
| Once the tag is pushed, GitHub will automatically detect the event and start the **Action Release** workflow. | ||
|
|
||
| #### Manual Triggering | ||
|
|
||
| In the event of a need to recreate a release, a GitHub Action can be run manually, as long as a tag exists for it. Go to `https://github.com/{ProjectName}/actions` and select | ||
| the "release" workflow in the left windowpane. Once selected, a new window will come up with a `Run workflow` button. Click on this, and answer | ||
| the following questions in the form: | ||
|
|
||
| * **Release Version to build and upload:** Enter the version number for the already created tag in the project to build the release from. It should be of the form `v.X.Y.Z`, or `v1.24.15`, for example. | ||
| * **Build only: Do not create the release** This defaults to `true`, allowing you to do the preliminary checking to see if everything is in place to build the release. If you select `true`, the release will **NOT** be built. If you select `false`, the release will attempt to build. | ||
| * **Send Mail to [email protected]** This defaults to `false`. If set to true, an email will be generated and sent to the [email protected] page announcing the new release for the project. | ||
|
|
||
| ## 🔑 Permissions and Requirements | ||
|
|
||
| This workflow requires elevated permissions to interact with the GitHub API for generating notes and creating the release object. | ||
|
|
||
| To ensure the workflow runs successfully, the job configuration must include the following permissions block, granting the default `GITHUB_TOKEN` the ability to write: | ||
|
|
||
| ```yaml | ||
| jobs: | ||
| release: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write # REQUIRED to create the release and fetch content | ||
| steps: | ||
| # ... | ||
| ``` | ||
|
|
||
| 🧩 Key Actions Used (Inferred) | ||
| The automation process relies on the following GitHub Actions: | ||
|
|
||
| Action Name Purpose | ||
| actions/checkout@v5 Downloads a copy of the repository code to the runner. | ||
| gableroux/[email protected] Generates the Markdown content for the release notes based on the commit history and merged PRs between tags. | ||
| dawidd6/[email protected] Create and formats email if requested. | ||
|
|
||
| 🛑 Troubleshooting | ||
| If the workflow fails with an error, such as the AxiosError: Request failed with status code 404 (a common GitHub API error in release actions), consider the following: | ||
|
|
||
| Check Permissions: Ensure your workflow or specific job has explicitly set permissions: contents: write to allow the default GITHUB_TOKEN to create the release. | ||
|
|
||
| Verify Tags: Confirm that the tag you pushed exactly matches the pattern the workflow is listening for (e.g., v*). | ||
|
|
||
| Previous Tag Existence: For release note generation to work correctly, a previous tag must exist to define the change range. Ensure your repository has at least one prior version tag. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,216 @@ | ||
| # ----------------------------------------------------------------------------------------------------------- | ||
| # This is a GitHub Action that will automatically create a release after a tag is pushed into the project | ||
| # by someone, or by running from the "Actions" page of the project. The interface in the Actions page will | ||
| # ask for the Branch to run from, the Release Version to build, if it should create a release or just do | ||
| # an initial build, and finally, if mail should be sent to the [email protected] email distribution lists. | ||
| # ----------------------------------------------------------------------------------------------------------- | ||
| name: Release | ||
| on: | ||
| push: | ||
| tags: | ||
| - '*' | ||
|
|
||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: 'Release version to build and upload (e.g. "v9.8.7")' | ||
| required: true | ||
| buildonly: | ||
| description: 'Build only: Do not create release' | ||
| default: "true" # 'choice' type requires string value | ||
| type: choice | ||
| options: | ||
| - "true" # Must be quoted string, boolean value not supported. | ||
| - "false" | ||
| sendmail: | ||
| description: 'Send Mail to [email protected]?' | ||
| default: "false" # 'choice' type requires string value | ||
| type: choice | ||
| options: | ||
| - "true" # Must be quoted string, boolean value not supported. | ||
| - "false" | ||
|
|
||
| # Set the permission for this workflow | ||
| permissions: | ||
| contents: write | ||
|
|
||
| # ----------------------------------------------------------------------------------------------------------- | ||
| # Get the version of the tag from input or from a push of it. | ||
| # Then figure out the prior version of the project. | ||
| # ----------------------------------------------------------------------------------------------------------- | ||
| jobs: | ||
| check: | ||
| name: Check | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Determine Version | ||
| id: getversion | ||
| run: | | ||
| if [[ -z "${{ inputs.version }}" ]] | ||
| then | ||
| VERSION=${{ github.ref_name }} | ||
| else | ||
| VERSION=${{ inputs.version }} | ||
| fi | ||
| if ! grep -Eq 'v[0-9]+(\.[0-9]+(\.[0-9]+(-.+)?)?)?$' <<<"$VERSION" | ||
| then | ||
| echo "Unable to parse release version '$VERSION' from github event JSON, or workflow 'version' input." | ||
| exit 1 | ||
| fi | ||
|
|
||
| if grep -Eq '.+-dev$' <<<"$VERSION" | ||
| then | ||
| echo "Refusing to process a "-dev" version '$VERSION'" | ||
| exit 1 | ||
| fi | ||
| prevrelease=$(curl --retry 3 --silent -m 10 --connect-timeout 5 "https://api.github.com/repos/${{ github.repository }}/releases/latest") | ||
| PRIORVERSION=$(echo "$prevrelease" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') >> $GITHUB_OUTPUT | ||
| echo "version=$VERSION" >> $GITHUB_OUTPUT | ||
| echo "priorversion=$PRIORVERSION" >> $GITHUB_OUTPUT | ||
| echo "::notice::Building $VERSION" | ||
| echo "::notice::With Prior Version $PRIORVERSION" | ||
| echo "::notice::For the project ${{ github.event.repository.name }}" | ||
|
|
||
| - name: Just check, or build the release? | ||
| id: buildonly | ||
| run: | | ||
| # The 'tag' trigger will not have a 'buildonly' input set. Handle | ||
| # this case in a readable/maintainable way. | ||
| if [[ -z "${{ inputs.buildonly }}" ]] | ||
| then | ||
| BUILDONLY="false" | ||
| else | ||
| BUILDONLY=${{ inputs.buildonly }} | ||
| fi | ||
| echo "buildonly=$BUILDONLY" >> $GITHUB_OUTPUT | ||
|
|
||
| outputs: | ||
| version: ${{ steps.getversion.outputs.version }} | ||
| priorversion: ${{ steps.getversion.outputs.priorversion }} | ||
| buildonly: ${{ steps.buildonly.outputs.buildonly }} | ||
|
|
||
| # ----------------------------------------------------------------------------------------------------------- | ||
| # Start the release process | ||
| # ----------------------------------------------------------------------------------------------------------- | ||
| release: | ||
| name: Create Release | ||
| runs-on: ubuntu-latest | ||
| if: needs.check.outputs.buildonly == 'false' | ||
| needs: [check] | ||
| permissions: | ||
| contents: write | ||
| env: | ||
| VERSION: ${{needs.check.outputs.version}} | ||
| PRIORVERSION: ${{needs.check.outputs.priorversion}} | ||
|
|
||
| steps: | ||
| - name: Checkout the main branch of this repository | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| ref: ${{needs.check.outputs.version}} | ||
|
Comment on lines
+107
to
+110
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is duplicated in the step below
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ouch, you're right! |
||
|
|
||
| - name: Touch release notes file | ||
| run: | | ||
| touch $VERSION-release-notes.md | ||
|
Comment on lines
+112
to
+114
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you need this if you're using the changelog action below
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't need it if they're generating the release note, but I do need it if they decide to pull the release notes from file instead. |
||
|
|
||
| # ----------------------------------------------------------------------------------------------------------- | ||
| # Create the Changelog | ||
| # ----------------------------------------------------------------------------------------------------------- | ||
| - name: Conventional Changelog Action | ||
| id: changelog | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| uses: gableroux/[email protected] | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| base_tag: ${{ needs.check.outputs.priorversion }} | ||
| head_tag: ${{ github.sha }} | ||
| repository: ${{ github.repository }} | ||
| auto_detect_new_contributors: 'true' | ||
|
|
||
| # ----------------------------------------------------------------------------------------------------------- | ||
| # Create the Release | ||
| # ----------------------------------------------------------------------------------------------------------- | ||
| - name: Create release | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| title=$VERSION | ||
| if [[ $VERSION == *-rc* ]]; then | ||
| RC="--prerelease" | ||
| title="${title/rc/"RC"}" | ||
| else | ||
| # check if this version should not be marked latest | ||
| vers=${VERSION#"v"} | ||
| priorversion=${PRIORVERSION#"v"} | ||
| echo "::notice::With Prior Version ${priorversion}" | ||
| echo "::notice::With New Version ${vers}" | ||
|
|
||
| # sort -V -C returns 0 if args are ascending version order | ||
| if !(echo "${priorvers},${vers}" | tr ',' '\n' | sort -V -C) | ||
| then | ||
| LATEST="--latest=false" | ||
| fi | ||
| fi | ||
|
|
||
| # If we're generating the release notes, put the generated ones in the file. | ||
| releasenotes="$VERSION-release-notes.md" | ||
| echo "${{ steps.changelog.outputs.notes }}" > $releasenotes | ||
|
|
||
| gh release create $VERSION \ | ||
| -t $title \ | ||
| --notes-file $releasenotes \ | ||
| --verify-tag \ | ||
| $RC \ | ||
| $LATEST | ||
|
|
||
| # ----------------------------------------------------------------------------------------------------------- | ||
| # If requested, let's send an email notification if we're creating the release. | ||
| # ----------------------------------------------------------------------------------------------------------- | ||
| notification: | ||
| name: Email notification | ||
| runs-on: ubuntu-latest | ||
| needs: [check, release] | ||
| if: needs.check.outputs.buildonly == 'false' && inputs.sendmail == 'true' | ||
| steps: | ||
| - name: Format release email | ||
| id: format | ||
| env: | ||
| VERSION: ${{ needs.check.outputs.version }} | ||
| run: | | ||
| if grep -Eq '.+-rc' <<<"$VERSION" | ||
| then | ||
| RC_PREFIX="candidate " | ||
| fi | ||
|
|
||
| echo "mail_subj=${{ github.event.repository.name }} ${RC_PREFIX}${VERSION} Released" >> $GITHUB_OUTPUT | ||
|
|
||
| cat <<EOF>email_body.txt | ||
| Hi all, | ||
|
|
||
| Containers-lib ${RC_PREFIX}${VERSION} is now available. You may view the full details at | ||
| https://github.com/${{ github.repository }}/releases/tag/$VERSION | ||
|
|
||
| Release ${RC_PREFIX}Notes: | ||
| -------------- | ||
| EOF | ||
|
|
||
| echo ${{ secrets.GITHUB_TOKEN }} | gh auth login --with-token | ||
| gh release view $VERSION \ | ||
| --repo ${{ github.repository }} --json=body --jq '.body' >> email_body.txt | ||
|
|
||
| # If the job fails, permit the operator to observe the contents if helpful. | ||
| - name: Provide release e-mail contents for examination | ||
| run: cat email_body.txt | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Luap99 it's created above at line 188 |
||
| - name: Send release notification e-mail | ||
| # Ref: https://github.com/dawidd6/action-send-mail | ||
| uses: dawidd6/[email protected] | ||
| with: | ||
| server_address: ${{secrets.ACTION_MAIL_SERVER}} | ||
| server_port: 465 | ||
| username: ${{secrets.ACTION_MAIL_USERNAME}} | ||
| password: ${{secrets.ACTION_MAIL_PASSWORD}} | ||
| subject: ${{ steps.format.outputs.mail_subj }} | ||
| to: Podman List <[email protected]> | ||
| from: ${{secrets.ACTION_MAIL_SENDER}} | ||
| body: file://./email_body.txt | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is inside the code block, probably need to move it out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed!