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

OSOE-735: Introduce versioning and releases #325

Merged
merged 37 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2507da9
Create Action to automatically set LGHA refs to an expected value; Cr…
davidpuplava Feb 9, 2024
61010f6
Remove empty lines from tag and release workflow
davidpuplava Feb 9, 2024
9c30364
Refactor based on feedback; Force push changes to tag
davidpuplava Feb 10, 2024
3641fd6
Merge remote-tracking branch 'origin/dev' into issue/OSOE-735
davidpuplava Feb 10, 2024
f2c1fbb
Handle special GHA refs such as spelling action that explicitly refer…
davidpuplava Feb 10, 2024
e7f93de
Remove extra whitespace
davidpuplava Feb 10, 2024
8d30e18
Merge branch 'dev' into issue/OSOE-735
davidpuplava Feb 14, 2024
def22e7
Refactor tag version to be reusable and take a secret; Add starter wo…
davidpuplava Feb 14, 2024
859c77d
Rmove whitespace
davidpuplava Feb 14, 2024
40dfb89
Merge branch 'dev' into issue/OSOE-735
davidpuplava Feb 20, 2024
9e8ae8c
Merge remote-tracking branch 'origin/dev' into issue/OSOE-735
BenedekFarkas Feb 28, 2024
c5281cc
Update readme to include information on automatic versioning
davidpuplava Mar 9, 2024
4ee3af6
Line wrap yaml descriptions to 120 characters
davidpuplava Mar 9, 2024
66de866
Surface the set-gha-refs action parameters up to workflow
davidpuplava Mar 9, 2024
08bf3cf
Lock external acation stefanzweifel/git-auto-commit-action to specifi…
davidpuplava Mar 9, 2024
eed4713
Add empty lines between steps for readability
davidpuplava Mar 9, 2024
ab3535e
Use LGHA Set-GitHubOutput script for output
davidpuplava Mar 9, 2024
32030b6
Update readme to link to externally used action, add spell check igno…
davidpuplava Mar 9, 2024
6802134
A bit of code styling/simplification
BenedekFarkas Mar 11, 2024
f19459c
Updating Readme wording in "Versioning, Tags and Releases" and a bit …
BenedekFarkas Mar 11, 2024
36bbcef
Simplify code, fix small bug with GitHub output key name
davidpuplava Mar 14, 2024
fd52bc0
Add paragraph about why we version LGHA and add clearer formating for…
davidpuplava Mar 14, 2024
e0ce7b5
Refactor external action ncipollo/release-action into internal action…
davidpuplava Mar 14, 2024
a102798
Fix spelling errors
davidpuplava Mar 14, 2024
ee31067
Update ref to publish-nuget action which changed in this OSOE-735
davidpuplava Mar 14, 2024
6fb17de
Remove trailing spaces to satisfy linting
davidpuplava Mar 14, 2024
1667cd2
Fix incorrect GitHub Action expression syntax
davidpuplava Mar 14, 2024
6c0127f
Fix path for setting up scripts
davidpuplava Mar 14, 2024
004e19b
Ensure repo is checked out before setting up scripts
davidpuplava Mar 14, 2024
2b47381
A bit of code styling in release-action
BenedekFarkas Mar 14, 2024
12492f3
Removing deprecated parameter from release-action
BenedekFarkas Mar 14, 2024
bbc033e
Minor wording improvement
BenedekFarkas Mar 14, 2024
05a109a
Simplify regex for GitHub Action references
davidpuplava Mar 15, 2024
4d5e3a8
Fix typo for matched line number
davidpuplava Mar 15, 2024
a954acd
Merge branch 'issue/OSOE-735' of https://github.com/Lombiq/GitHub-Act…
davidpuplava Mar 15, 2024
24f5ce6
Remove unused inputs copied from external GitHub Action for LGHA cent…
davidpuplava Mar 15, 2024
a4eaf75
Reverting branch references to dev
BenedekFarkas Mar 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/actions/publish-nuget/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,8 @@ runs:
path: artifacts
retention-days: ${{ inputs.nuget-artifact-retention-days }}

# This is not in its own action because it's all very specific to this NuGet publishing.
- name: Create Release
# v1.11.2
uses: ncipollo/release-action@18eadf9c9b0f226f47f164f5373c6a44f0aae169
uses: Lombiq/GitHub-Actions/.github/actions/release-action@dev
# This is to prevent creating releases when pushing tags for issue-specific pre-releases like
# v4.3.1-alpha.osoe-86.
if: "!contains(steps.setup.outputs.publish-version, '-')"
Expand Down
51 changes: 51 additions & 0 deletions .github/actions/release-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Create Release
description: >
Runs ncipollo/release-action. Exists only to centralize which version of the action we use. Intentionally not
documented in Actions.md since it's only meant for internal use.

# Copied from https://github.com/ncipollo/release-action/blob/v1.11.2/action.yml. Formatted to wrap long
# descriptions. Removed inputs not used by Lombiq GitHub-Actions.
inputs:
allowUpdates:
description: >
An optional flag which indicates if we should update a release if it already exists. Defaults to false.
required: false
default: ''
artifacts:
description: >
An optional set of paths representing artifacts to upload to the release. This may be a single path or a comma
delimited list of paths (or globs).
required: false
default: ''
generateReleaseNotes:
description: 'Indicates if release notes should be automatically generated.'
required: false
default: 'false'
tag:
description: 'An optional tag for the release. If this is omitted the git ref will be used (if it is a tag).'
required: false
default: ''

outputs:
id:
description: 'The identifier of the created release.'
value: ${{ steps.create-release.outputs.id }}
html_url:
description: 'The HTML URL of the release.'
value: ${{ steps.create-release.outputs.html_url }}
upload_url:
description: 'The URL for uploading assets to the release.'
value: ${{ steps.create-release.outputs.upload_url }}

runs:
using: 'composite'
steps:
- name: Create Release
id: create-release
# v1.11.2
uses: ncipollo/release-action@18eadf9c9b0f226f47f164f5373c6a44f0aae169
with:
allowUpdates: ${{ inputs.allowUpdates }}
artifacts: ${{ inputs.artifacts }}
generateReleaseNotes: ${{ inputs.generateReleaseNotes }}
tag: ${{ inputs.tag }}
46 changes: 46 additions & 0 deletions .github/actions/set-gha-refs/Set-Called-GHA-Refs.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
param(
[String[]] $CalledRepoBaseIncludeList,
[String[]] $AdditionalPatternIncludeList,
[String[]] $PathIncludeList,
[String[]] $FileIncludeList,
[String] $ExpectedRef
)

if ($CalledRepoBaseIncludeList.Count -eq 0)
{
Write-Output '::warning file=Check-Called-GHA-refs.ps1,line10::CalledRepoBaseIncludeList is empty which is unexpected. If this was intentional, you can ignore this warning.'
}
else
{
$CalledRepoBaseIncludeList = $CalledRepoBaseIncludeList.ForEach({ 'uses:\s*' + $PSItem + '.*@(?<ref>[\w\./-]*)' })

$matchedRefs = Get-ChildItem -Path $PathIncludeList -Include $FileIncludeList -Force -Recurse |
Select-String -Pattern $CalledRepoBaseIncludeList

$additionalRefs = Get-ChildItem -Path $PathIncludeList -Include $FileIncludeList -Force -Recurse |
Select-String -Pattern $AdditionalPatternIncludeList

$matchedRefs = $matchedRefs + $additionalRefs

if ($matchedRefs.Count -gt 0)
{
foreach ($matched in $matchedRefs)
{
$oldline = $matched.Line
$newline = $matched.Line -Replace $matched.Matches[0].Groups['ref'].Value, "$ExpectedRef"

if ($oldine -ne $newline)
{
Write-Output "$oldline => $newline"

$filename = $matched.RelativePath($pwd)
$linenumber = $matched.LineNumber
$title = "GHA Ref pinned to '$ExpectedRef'"

(Get-Content $filename).Replace($oldline, $newline) | Set-Content $filename

Write-Output "::notice file=$filename,line=$linenumber,title=$title::GHA Ref changed to '$ExpectedRef'"
}
}
}
}
55 changes: 55 additions & 0 deletions .github/actions/set-gha-refs/action.yml
BenedekFarkas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Set GitHub Actions References
description: >
Explicitly sets all called GitHub Action and Workflow references to an expected version.

inputs:
path-include-list:
required: false
default: '@(".github")'
description: >
PowerShell string array of paths, relative to the repository root, to search for GHA files, e.g. '@(".github")' or
'@(".github/actions", ".github/workflows")'. The parameter must be a PowerShell string array.
file-include-list:
required: false
default: '@("*.yml","*.yaml")'
description: >
PowerShell string array of file name patterns to include when evaluating GHA files, e.g. '@("*.yml")' or
'@("*.yml", "*.yaml")'. The parameter must be a PowerShell string array.
called-repo-base-include-list:
required: false
default: '@("${{ github.repository }}")'
description: >
PowerShell string array of repository base URLs to include when evaluating called GHA Workflows and Actions, e.g
'@("Lombiq/GitHub-Actions")' or '@("Lombiq/GitHub-Actions", "Lombiq/Open-Source-Orchard-Core-Extensions")'. The
parameter must be a PowerShell string array.
additional-pattern-include-list:
BenedekFarkas marked this conversation as resolved.
Show resolved Hide resolved
required: false
default: '@()'
description: >
PowerShell string array of additional RegEx patterns to include when searching for branch references that need to
be updated, e.g. 'https://raw.githubusercontent.com/Lombiq/GitHub-Actions/(?<ref>[\w\./-]*)/.github/'.
The pattern MUST include a regex named capture group (?<ref>[\w\./-]*) so the captured ref can be
updated correctly. The parameter must be a PowerShell string array.
expected-ref:
required: true
description: The expected reference value to set for all called GHA Workflows and Actions.

runs:
using: 'composite'
steps:
- name: Setup
shell: pwsh
run: |
"${{ github.action_path }}" >> $Env:GITHUB_PATH

- name: Set References
shell: pwsh
run: |
$params = @{
PathIncludeList = ${{ inputs.path-include-list }}
FileIncludeList = ${{ inputs.file-include-list }}
CalledRepoBaseIncludeList = ${{ inputs.called-repo-base-include-list }}
AdditionalPatternIncludeList = ${{ inputs.additional-pattern-include-list }}
ExpectedRef = "${{ inputs.expected-ref }}"
}
Set-Called-GHA-Refs @params
16 changes: 16 additions & 0 deletions .github/workflows/tag-version-this-repo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Tag Version (this repo)
Piedone marked this conversation as resolved.
Show resolved Hide resolved

on:
push:
branches:
- release/**

jobs:
run:
name: Tag Version Automation
if: github.event.pusher.name != 'LombiqBot'
BenedekFarkas marked this conversation as resolved.
Show resolved Hide resolved
uses: Lombiq/GitHub-Actions/.github/workflows/tag-version.yml@dev
with:
additional-pattern-include-list: '@("https://raw.githubusercontent.com/Lombiq/GitHub-Actions/(?<ref>[\w\./-]*)/.github")'
secrets:
TAG_VERSION_TOKEN: ${{ secrets.LOMBIQBOT_GITHUB_PERSONAL_ACCESS_TOKEN }}
112 changes: 112 additions & 0 deletions .github/workflows/tag-version.yml
BenedekFarkas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Tag Version

on:
workflow_call:
secrets:
# We can't access org secrets here so they need to be passed in.
TAG_VERSION_TOKEN:
required: false
description: >
An authentication token, like a personal access token (PAT), that provides 'Workflow' permission with write
access to the workflow files of the repository and can be used to modify GitHub actions and workflows. This is
necessary because when a pull request is merged while being authenticated with the default GITHUB_TOKEN of a
workflow run, then the merge won't trigger other workflows (like a build workflow on the target branch). This
is an intentional limitation, see:
https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow.
Thus, we need to use an alternative authentication token. See
https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
for info on how to create PATs; you'll need one with the "work" scope. We recommend creating such a token from
under a bot user account only used for such operations, so it's not tied to a natural person.
inputs:
path-include-list:
description: >
PowerShell string array of paths, relative to the repository root, to search for GHA files, e.g.
'@(".github")' or '@(".github/actions", ".github/workflows")'. The parameter must be a PowerShell string
array.
required: false
default: '@(".github")'
type: string
file-include-list:
required: false
default: '@("*.yml","*.yaml")'
description: >
PowerShell string array of file name patterns to include when evaluating GHA files, e.g. '@("*.yml")' or
'@("*.yml", "*.yaml")'. The parameter must be a PowerShell string array.
type: string
called-repo-base-include-list:
required: false
default: '@("${{ github.repository }}")'
description: >
PowerShell string array of repository base URLs to include when evaluating called GHA Workflows and Actions,
e.g '@("Lombiq/GitHub-Actions")' or '@("Lombiq/GitHub-Actions",
"Lombiq/Open-Source-Orchard-Core-Extensions")'. The parameter must be a PowerShell string array.
type: string
additional-pattern-include-list:
required: false
default: '@()'
description: >
PowerShell string array of additional RegEx patterns to include when searching for branch references that need
to be updated, e.g.
'https://raw.githubusercontent.com/Lombiq/GitHub-Actions/(?<ref>[\w\./-]*)/.github/'. The pattern
MUST include a regex named capture group (?<ref>[\w\./-]*) so the captured ref can be updated
correctly. The parameter must be a PowerShell string array.
type: string
expected-ref:
required: false
default: '${{ github.ref_name }}'
description: The expected reference value to set for all called GHA Workflows and Actions.
type: string

jobs:
run:
name: Set GitHub Action/Workflow to Version Tag
runs-on: ubuntu-latest
defaults:
run:
shell: pwsh
steps:

- name: Checkout Repository
uses: Lombiq/GitHub-Actions/.github/actions/checkout@dev
with:
token: ${{ secrets.TAG_VERSION_TOKEN }}

- name: Setup Scripts
run: |
(Resolve-Path "Scripts").Path >> $Env:GITHUB_PATH

- name: Determine Version Tag Name from Branch Name
BenedekFarkas marked this conversation as resolved.
Show resolved Hide resolved
id: determine-tag
run: |
$tagname = "${{ inputs.expected-ref }}" -replace 'release/', ''
Set-GitHubOutput -Key 'tagname' -Value $tagname

- name: Set Ref for GitHub Actions and Workflows
uses: Lombiq/GitHub-Actions/.github/actions/set-gha-refs@dev
with:
path-include-list: ${{ inputs.path-include-list }}
file-include-list: ${{ inputs.file-include-list }}
called-repo-base-include-list: ${{ inputs.called-repo-base-include-list }}
additional-pattern-include-list: ${{ inputs.additional-pattern-include-list }}
expected-ref: '${{ steps.determine-tag.outputs.tagname }}'

- name: Commit and Push Changes
uses: stefanzweifel/git-auto-commit-action@8756aa072ef5b4a080af5dc8fef36c5d586e521d # v5
with:
commit_message: 'Set GitHub Actions/Workflows to tag ${{ steps.determine-tag.outputs.tagname }}'
tagging_message: ${{ steps.determine-tag.outputs.tagname }}

- name: Force Push Tag
continue-on-error: true
BenedekFarkas marked this conversation as resolved.
Show resolved Hide resolved
run: git push --tags --force
Piedone marked this conversation as resolved.
Show resolved Hide resolved

- name: Create Release
uses: Lombiq/GitHub-Actions/.github/actions/release-action@dev
# This is to prevent creating releases when pushing tags for issue-specific pre-releases like
# v4.3.1-alpha.osoe-86.
if: "!contains(steps.determine-tag.outputs.tagname, '-')"
with:
allowUpdates: true
generateReleaseNotes: true
tag: ${{ steps.determine-tag.outputs.tagname }}

22 changes: 22 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,25 @@ Bug reports, feature requests, comments, questions, code contributions and love
This project is developed by [Lombiq Technologies](https://lombiq.com/). Commercial-grade support is available through Lombiq.

To ensure that when changing actions or workflows their references to other actions/workflows are up-to-date (i.e. instead of `@dev` they reference each other with `@current-branch`) the [Validate GitHub Actions Refs workflow](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/workflows/validate-this-gha-refs.yml) will fail if references are incorrect. This is the case also if after a pull request approve that references don't point to the target branch; before merging, that should be fixed, otherwise merging via the merge queue will fail.

## Versioning, Tags and Releases

To release versions of Lombiq GitHub Actions, and allow consumers to reference a specific version of a reusable workflow or composite action (e.g. `@v1.0`), we employ some automation to do this in a consistent and predictable way.
See [issue #284 "Introduce versioning and releases (OSOE-735)"](https://github.com/Lombiq/GitHub-Actions/issues/284) <!-- #spell-check-ignore-line -->
for additional details on why we do this.

New versions of Lombiq GitHub Actions are automatically tagged using the [Tag Version (this repo)](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/workflows/tag-version-this-repo.yml) workflow. This workflow is triggered for release branches with a name that matches the `release/**` pattern (e.g. `release/v1.0`, `release/v2.0-alpha`, etc.).

The create a new release, create a new branch following the above naming convention at the commit to be released and push it.

When you push your new release branch, the following things happen automatically:

1. The [Tag Version (this repo)](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/workflows/tag-version-this-repo.yml) workflow runs and calls the reusable workflow [Tag Version](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/workflows/tag-version.yml).
2. The [Tag Version](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/workflows/tag-version.yml) workflow calls the [Set GitHub Actions References](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/actions/set-gha-refs/action.yml) reusable action.
3. The [Set GitHub Actions References](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/actions/set-gha-refs/action.yml) action recursively searches all files in the `.github` folder to find each call to a GitHub Action or Workflow contained in this repository.
4. By default, references to called actions and workflows targeting the release branch (see above) are string replaced with the version name (e.g. `v1.0`).
- Additionally, the [Set GitHub Actions References](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/actions/set-gha-refs/action.yml) action has a parameter called [additional-pattern-include-list](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/actions/set-gha-refs/action.yml#L24) which allows for replacing `release/v1.0` under special circumstances such as for the [spelling action explicit file reference](https://github.com/Lombiq/GitHub-Actions/blob/dev/.github/actions/spelling/action.yml#L133) scenario.
5. The [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action/commit/8756aa072ef5b4a080af5dc8fef36c5d586e521d) action is used to automatically: <!-- #spell-check-ignore-line -->
- Commit the updated files to the `release/v1.0` branch.
- Create a new git tag using the release name (e.g. `v1.0`).
6. Tags are force pushed to update the `v1.0` tag if it needs to be updated.
Loading