Skip to content

Commit

Permalink
feat: add support for rust to release workflows
Browse files Browse the repository at this point in the history
  • Loading branch information
galargh committed Jul 17, 2024
1 parent e99722a commit 6203866
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 68 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/copy-templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ jobs:
TypeScript:
files:
- .github/workflows/js-test-and-release.yml
Rust:
files:
- .github/workflows/releaser.yml
- .github/workflows/release-check.yml
- .github/workflows/tagpush.yml
override: |
common:
force: ${{ github.event.inputs.force }}
Expand Down
133 changes: 76 additions & 57 deletions .github/workflows/release-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ on:
required: false
type: string
default: ${{ format('["{0}"]', github.event.repository.default_branch) }}
sources:
required: false
type: string
default: '["version.json"]'

jobs:
release-check:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
source: ${{ fromJSON(inputs.sources) }}
steps:
- run: echo "EOF=EOF$RANDOM" >> $GITHUB_ENV
- id: pr
Expand Down Expand Up @@ -43,20 +51,31 @@ jobs:
uses: ipdxco/unified-github-workflows/.github/actions/read-go-mod@main
- uses: actions/setup-go@v5
with:
go-version: ${{ fromJSON(steps.go-mod.outputs.json).Go }}.x
go-version: ${{ fromJSON(steps.go-mod.outputs.json).Go && format('{0}.x', fromJSON(steps.go-mod.outputs.json).Go) || 'stable' }}
cache: false
- id: version
name: Determine version
env:
GITHUB_TOKEN: ${{ github.token }}
SOURCE: ${{ matrix.source }}
HEAD_FULL_NAME: ${{ fromJSON(steps.pr.outputs.json).head.repo.full_name }}
HEAD_SHA: ${{ fromJSON(steps.pr.outputs.json).head.sha }}
run: |
root="$(dirname "$SOURCE")"
echo "root=$root" | tee -a $GITHUB_OUTPUT
if [[ "$root" == "." ]]; then
prefix="v"
else
prefix="$root/v"
fi
echo "prefix=$prefix" | tee -a $GITHUB_OUTPUT
# If `version.json` file doesn't exists, `version` is `""` and `404` is printed on stderr.
# The step won't be marked as a failure though because the error happens in a subshell.
version="$(gh api -X GET "repos/$HEAD_FULL_NAME/contents/version.json" -f ref="$HEAD_SHA" --jq '.content' | base64 -d | jq -r '.version')"
echo "version=$version"
echo "version=$version" >> $GITHUB_OUTPUT
content="$(gh api -X GET "repos/$HEAD_FULL_NAME/contents/$SOURCE" -f ref="$HEAD_SHA" --jq '.content' | base64 -d)"
version="$(yq -r '.workspace.package.version // .package.version // .version // ""' <<< "$content")"
version="${version#"$prefix"}"
echo "version=$version" | tee -a $GITHUB_OUTPUT
echo "tag=${prefix}${version}" | tee -a $GITHUB_OUTPUT
- id: branch
name: Check if the branch is a release branch
if: steps.version.outputs.version != ''
Expand All @@ -78,12 +97,12 @@ jobs:
name: Check if the tag already exists
if: steps.version.outputs.version != ''
env:
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
ALLOWED: ${{ steps.branch.outputs.release == 'true' || contains(fromJSON(steps.pr.outputs.json).labels.*.name, 'release') }}
run: |
git fetch origin --tags
status=0
git rev-list "$VERSION" &> /dev/null || status=$?
git rev-list "$TAG" &> /dev/null || status=$?
if [[ $status == 0 ]]; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "needed=false" >> $GITHUB_OUTPUT
Expand All @@ -97,21 +116,23 @@ jobs:
- name: Check version
if: steps.tag.outputs.needed == 'true'
env:
VERSION: ${{ steps.version.outputs.version }}
VERSION: v${{ steps.version.outputs.version }}
# semver fails if the version is not valid (e.g. v0.1 would fail)
run: semver "$VERSION"
- id: prerelease
if: steps.tag.outputs.needed == 'true'
name: Check if this is a pre-release
env:
VERSION: ${{ steps.version.outputs.version }}
VERSION: v${{ steps.version.outputs.version }}
# semver -r fails if the version is not valid or if it is a pre-release (e.g v0.1 or v0.1.0-rc1 would fail)
run: echo "prerelease=$(semver -r "$VERSION" && echo false || echo true)" >> $GITHUB_OUTPUT
run: echo "prerelease=$(semver -r "$VERSION" && echo false || echo true)" | tee -a $GITHUB_OUTPUT
- id: prev
name: Determine version number to compare to
if: steps.tag.outputs.needed == 'true'
env:
VERSION: ${{ steps.version.outputs.version }}
PREFIX: ${{ steps.version.outputs.prefix }}
VERSION: v${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
PRERELEASE: ${{ steps.prerelease.outputs.prerelease }}
# We need to determine the version number we want to compare to,
# taking into account that this might be a (patch) release on a release branch.
Expand All @@ -123,85 +144,83 @@ jobs:
run: |
git fetch origin --tags
go install github.com/marten-seemann/semver-highest@fcdc98f8820ff0e6613c1bee071c096febd98dbf
vs=$(git tag | paste -sd , -)
ts=$(git tag | grep "^${PREFIX}" | paste -sd , -)
vs=$(echo "$ts" | sed "s/^${PREFIX}/v/g")
if [[ ! -z "$vs" ]]; then
v=$(semver-highest -target "$VERSION" -versions "$vs" -prerelease="$PRERELEASE")
v=$(semver-highest -target "$VERSION" -versions "$vs" -prerelease="$prerelease")
status=$?
if [[ $status != 0 ]]; then
echo $v
echo "v=$v"
exit $status
fi
echo "version=$v" >> $GITHUB_OUTPUT
echo "tag=$PREFIX${v%v}" | tee -a $GITHUB_OUTPUT
fi
- id: git-diff
name: run git diff on go.mod file(s)
if: steps.tag.outputs.needed == 'true' && steps.prev.outputs.version != ''
name: Run git diff on configuration file(s)
if: steps.tag.outputs.needed == 'true' && steps.prev.outputs.tag != ''
env:
PREV_VERSION: ${{ steps.prev.outputs.version }}
PREV_TAG: ${{ steps.prev.outputs.tag }}
run: |
# First get the diff for the go.mod file in the root directory...
output=$(git diff "$PREV_VERSION..HEAD" -- './go.mod')
# ... then get the diff for all go.mod files in subdirectories.
# Note that this command also finds go.mod files more than one level deep in the directory structure.
output+=$(git diff "$PREV_VERSION..HEAD" -- '*/go.mod')
# First get the diff for the go.mod/Cargo.toml file in the root directory...
output=$(git diff "$PREV_TAG..HEAD" -- './go.mod' './Cargo.toml')
# ... then get the diff for all go.mod/Cargo.toml files in subdirectories.
# Note that this command also finds go.mod/Cargo.toml files more than one level deep in the directory structure.
output+=$(git diff "$PREV_TAG..HEAD" -- '*/go.mod' '*/Cargo.toml')
if [[ -z "$output" ]]; then
output="(empty)"
fi
printf "output<<$EOF\n%s\n$EOF" "$output" >> $GITHUB_OUTPUT
- id: gorelease
name: Run gorelease
printf "output<<$EOF\n%s\n$EOF" "$output" | tee -a $GITHUB_OUTPUT
working-directory: ${{ steps.version.outputs.root }}
- id: language
name: Run language specific checks
if: steps.tag.outputs.needed == 'true' && steps.prev.outputs.version != ''
env:
PREV_VERSION: ${{ steps.prev.outputs.version }}
LANGUAGE: github.event.pull_request.base.repo.language
PREV_TAG: ${{ steps.prev.outputs.tag }}
# see https://github.com/golang/exp/commits/master/cmd/gorelease
run: |
go mod download
go install golang.org/x/exp/cmd/gorelease@f062dba9d201f5ec084d25785efec05637818c00 # https://cs.opensource.google/go/x/exp/+/f062dba9d201f5ec084d25785efec05637818c00
output=$((gorelease -base "$PREV_VERSION") 2>&1 || true)
printf "output<<$EOF\n%s\n$EOF" "$output" >> $GITHUB_OUTPUT
- id: gocompat
name: Check Compatibility
if: steps.tag.outputs.needed == 'true' && steps.prev.outputs.version != ''
env:
PREV_VERSION: ${{ steps.prev.outputs.version }}
run: |
go install github.com/smola/gocompat/cmd/gocompat@8498b97a44792a3a6063c47014726baa63e2e669 # v0.3.0
output=$(gocompat compare --go1compat --git-refs="$PREV_VERSION..HEAD" ./... || true)
if [[ -z "$output" ]]; then
output="(empty)"
echo "output<<$EOF" >> $GITHUB_OUTPUT
if [[ "$LANGUAGE" == "Go" ]]; then
go mod download
go install golang.org/x/exp/cmd/gorelease@f062dba9d201f5ec084d25785efec05637818c00 # https://cs.opensource.google/go/x/exp/+/f062dba9d201f5ec084d25785efec05637818c00
go install github.com/smola/gocompat/cmd/gocompat@8498b97a44792a3a6063c47014726baa63e2e669 # v0.3.0
echo "`gorelease` says:" >> $GITHUB_OUTPUT
echo "```" >> $GITHUB_OUTPUT
echo "Run gorelease"
(gorelease -base "$PREV_TAG") 2>&1 || true | tee -a $GITHUB_OUTPUT
echo "```" >> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
echo "`gocompat` says:" >> $GITHUB_OUTPUT
echo "```" >> $GITHUB_OUTPUT
echo "Run gocompat"
(gocompat compare --go1compat --git-refs="$PREV_TAG..HEAD" ./...) 2>&1 || true | tee -a $GITHUB_OUTPUT
echo "```" >> $GITHUB_OUTPUT
fi
printf "output<<$EOF\n%s\n$EOF" "$output" >> $GITHUB_OUTPUT
echo "$EOF" >> $GITHUB_OUTPUT
working-directory: ${{ steps.version.outputs.root }}
- id: release
if: steps.tag.outputs.needed == 'true' && fromJSON(steps.pr.outputs.json).head.repo.full_name == fromJSON(steps.pr.outputs.json).base.repo.full_name
uses: galargh/action-gh-release@571276229e7c9e6ea18f99bad24122a4c3ec813f # https://github.com/galargh/action-gh-release/pull/1
with:
draft: true
tag_name: ${{ steps.version.outputs.version }}
tag_name: ${{ steps.version.outputs.tag }}
generate_release_notes: true
target_commitish: ${{ fromJSON(steps.pr.outputs.json).base.ref }}
- id: message
if: steps.tag.outputs.exists == 'false'
env:
SOURCE: ${{ matrix.source }}
HEADER: |
Suggested version: `${{ steps.version.outputs.version }}`
BODY: |
Comparing to: [${{ steps.prev.outputs.version }}](${{ fromJSON(steps.pr.outputs.json).base.repo.html_url }}/releases/tag/${{ steps.prev.outputs.version }}) ([diff](${{ fromJSON(steps.pr.outputs.json).base.repo.html_url }}/compare/${{ steps.prev.outputs.version }}..${{ fromJSON(steps.pr.outputs.json).head.label }}))
Comparing to: [${{ steps.prev.outputs.version }}](${{ fromJSON(steps.pr.outputs.json).base.repo.html_url }}/releases/tag/${{ steps.prev.outputs.tag }}) ([diff](${{ fromJSON(steps.pr.outputs.json).base.repo.html_url }}/compare/${{ steps.prev.outputs.tag }}..${{ fromJSON(steps.pr.outputs.json).head.label }}))
Changes in `go.mod` file(s):
Changes in configuration file(s):
```diff
${{ steps.git-diff.outputs.output }}
```
`gorelease` says:
```
${{ steps.gorelease.outputs.output }}
```
`gocompat` says:
```
${{ steps.gocompat.outputs.output }}
```
${{ steps.language.outputs.content }}
BODY_ALT: |
This is the first release of this module.
Expand All @@ -214,7 +233,7 @@ jobs:
DIFF_NOTICE: |
## Cutting a Release (and modifying non-markdown files)
This PR is modifying both `version.json` and non-markdown files.
This PR is modifying both `${{ matrix.source }}` and non-markdown files.
The Release Checker is not able to analyse files that are not checked in to `${{ fromJSON(steps.pr.outputs.json).base.ref }}`. This might cause the above analysis to be inaccurate.
Please consider performing all the code changes in a separate PR before cutting the release.
Expand All @@ -229,7 +248,7 @@ jobs:
## Automatically created GitHub Release
Pre-creating GitHub Releases on release PRs initiated from forks is not supported.
If you wish to prepare release notes yourself, you should create a draft GitHub Release for tag `${{ steps.version.outputs.version }}` manually.
If you wish to prepare release notes yourself, you should create a draft GitHub Release for tag `${{ steps.version.outputs.tag }}` manually.
The draft GitHub Release is going to be published when this PR is merged.
If you choose not to create a draft GitHub Release, a published GitHub Released is going to be created when this PR is merged.
Expand All @@ -251,7 +270,7 @@ jobs:
else
echo "$BODY_ALT" >> $GITHUB_OUTPUT
fi
diff="$(gh api -X GET "repos/$GITHUB_REPOSITORY/compare/$BASE_REF...$HEAD_LABEL" --jq '.files | map(.filename) | map(select(test("^(version\\.json|.*\\.md)$") | not)) | .[]')"
diff="$(gh api -X GET "repos/$GITHUB_REPOSITORY/compare/$BASE_REF...$HEAD_LABEL" --jq '.files | map(.filename)' | jq -r --arg source "$SOURCE" 'map(select(test("^(\($source)|.*\\.md)$") | not)) | .[]')"
if [[ "$diff" != "" ]]; then
echo "$DIFF_NOTICE" >> $GITHUB_OUTPUT
fi
Expand Down
40 changes: 31 additions & 9 deletions .github/workflows/releaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,48 @@ on:
required: false
type: string
default: ${{ format('["{0}"]', github.event.repository.default_branch) }}
sources:
required: false
type: string
default: '["version.json"]'
secrets:
UCI_GITHUB_TOKEN:
required: false

jobs:
releaser:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
source: ${{ fromJSON(inputs.sources) }}
steps:
- uses: actions/checkout@v4
- id: version
name: Determine version
run: jq -r .version version.json | xargs -I{} echo "version={}" | tee -a $GITHUB_OUTPUT
env:
SOURCE: ${{ matrix.source }}
run: |
prefix="$(dirname "$SOURCE")"
if [[ "$prefix" == "." ]]; then
prefix="v"
else
prefix="$prefix/v"
fi
echo "prefix=$prefix" | tee -a $GITHUB_OUTPUT
version="$(yq -r '.workspace.package.version // .package.version // .version // ""' "$SOURCE")"
version="${version#"$prefix"}"
echo "version=$version" | tee -a $GITHUB_OUTPUT
echo "tag=${prefix}${version}" | tee -a $GITHUB_OUTPUT
- id: latest
if: steps.version.outputs.version != ''
name: Determine latest version
env:
VERSION: ${{ steps.version.outputs.version }}
PREFIX: ${{ steps.version.outputs.prefix }}
TAG: ${{ steps.version.outputs.tag }}
run: |
git fetch origin --tags
echo -e "$VERSION\n$(git tag)" | sort -V | tail -n1 | xargs -I{} echo "latest={}" | tee -a $GITHUB_OUTPUT
echo -e "${TAG}\n$(git tag)" | grep "^${PREFIX}" | sort -V | tail -n1 | xargs -I{} echo "latest={}" | tee -a $GITHUB_OUTPUT
- id: branch
name: Check if the branch is a release branch
if: steps.version.outputs.version != ''
Expand Down Expand Up @@ -85,11 +107,11 @@ jobs:
name: Check if tag already exists
if: steps.branch.outputs.release == 'true' || steps.pr.outputs.release == 'true'
env:
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
run: |
git fetch origin --tags
status=0
git rev-list "$VERSION" &> /dev/null || status=$?
git rev-list "$TAG" &> /dev/null || status=$?
if [[ $status == 0 ]]; then
echo "exists=true" >> $GITHUB_OUTPUT
else
Expand All @@ -101,23 +123,23 @@ jobs:
uses: galargh/action-gh-release@571276229e7c9e6ea18f99bad24122a4c3ec813f # https://github.com/galargh/action-gh-release/pull/1
with:
draft: false
tag_name: ${{ steps.version.outputs.version }}
tag_name: ${{ steps.version.outputs.tag }}
generate_release_notes: true
target_commitish: ${{ github.sha }}
make_latest: ${{ steps.version.outputs.version == steps.latest.outputs.latest }}
make_latest: ${{ steps.version.outputs.prefix == 'v' && steps.version.outputs.tag == steps.latest.outputs.latest }}
token: ${{ secrets.UCI_GITHUB_TOKEN || github.token }}
- name: Create release.json
if: steps.release.outputs.id != ''
env:
RELEASE: |
{
"draft": false,
"version": "${{ steps.version.outputs.version }}",
"version": "${{ steps.version.outputs.tag }}",
"url": "${{ steps.release.outputs.url }}",
"id": "${{ steps.release.outputs.id }}",
"upload_url": "${{ steps.release.outputs.upload_url }}",
"assets": ${{ steps.release.outputs.assets }},
"make_latest": ${{ steps.version.outputs.version == steps.latest.outputs.latest }}
"make_latest": ${{ steps.version.outputs.prefix == 'v' && steps.version.outputs.tag == steps.latest.outputs.latest }}
}
run: jq . <<< "$RELEASE" > release.json
- name: Upload release.json
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### Added
- support for rust to release workflows

### Changed
- disable cache in setup-go action by default

Expand Down
4 changes: 3 additions & 1 deletion templates/.github/workflows/release-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Release Checker

on:
pull_request_target:
paths: [ 'version.json' ]
paths: ${{{ .github.languages | map(select(. == "Rust")) | if length == 0 then ["version.json"] else ["Cargo.toml"] end }}}
types: [ opened, synchronize, reopened, labeled, unlabeled ]
workflow_dispatch:

Expand All @@ -17,3 +17,5 @@ concurrency:
jobs:
release-check:
uses: ipdxco/unified-github-workflows/.github/workflows/release-check.yml@${{{ .config.versions.uci // (.source.tag | sub("\\.[^.\\-\\+]+(?=\\-|\\+|$)"; "")) }}}
with:
sources: '${{{ .github.languages | map(select(. == "Rust")) | if length == 0 then ["version.json"] else ["Cargo.toml"] end }}}'
Loading

0 comments on commit 6203866

Please sign in to comment.