Skip to content

Release Workflow

Release Workflow #98

Workflow file for this run

name: "Release Workflow"
# Manual trigger workflow to automatically setup, build and push a new release (or prerelease) on NPM
on:
workflow_dispatch:
inputs:
releaseType:
description: 'Release type'
required: true
default: 'prerelease'
type: choice
options:
- prerelease
- patch
- minor
- major
prereleaseName:
description: 'Prerelease name (ignore if release type is not `prerelease`)'
default: 'alpha'
type: string
concurrency:
group: "${{ github.workflow }}-${{ github.ref_name }}"
cancel-in-progress: true
jobs:
publish_version:
name: "Publish version"
runs-on: ubuntu-latest
steps:
- name: "Checkout repository"
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: "Setup"
uses: ./.github/actions/setup
- name: "Create version"
id: version
uses: actions/github-script@v6
with:
script: |
const refType = '${{ github.ref_type }}';
const refName = '${{ github.ref_name }}';
if (refType !== 'branch') {
console.log(`Release workflow can only be run from a branch.\n`);
process.exit(1);
}
const run = require('util').promisify(require('child_process').exec);
const lodash = require('lodash');
const semver = require('semver');
const releaseType = '${{ inputs.releaseType }}' || 'prerelease';
console.log(`Release type: ${releaseType}`);
const prereleaseName = lodash.kebabCase('${{ inputs.prereleaseName }}' || 'alpha');
const getVersion = (tag) => run(`npm view @lumx/core@${tag} version`).then(({ stdout }) => stdout.trim());
const npmLatestVersion = await getVersion('latest');
if (releaseType !== 'prerelease') {
// Exit if not on master
if (refName !== 'master') {
console.log(`New ${releaseType} release can only be created from master.\n`);
process.exit(1);
}
const localVersion = require('./lerna.json').version;
if (localVersion !== npmLatestVersion) {
console.log(`NPM latest version (${npmLatestVersion}) does not match the local latest version (${localVersion}).\n`);
process.exit(1);
}
// Check that the changelog has unreleased changes.
try {
await run('yarn changelog-verify --unreleased');
} catch(err) {
console.log(err);
process.exit(1);
}
} else {
console.log(`Prerelease name: ${prereleaseName}`);
}
// Get NPM dist tag
const distTag = releaseType === 'prerelease' ? prereleaseName : 'latest';
console.log(`NPM dist tag: ${distTag}`);
// Get base version (version from which to increment)
let baseVersion = await getVersion(distTag)
// Prerelease should start with latest NPM version + patch (ex: 'v1.0.0' => 'v1.0.1-alpha.0')
if (releaseType === 'prerelease' && (!baseVersion || !baseVersion.startsWith(semver.inc(npmLatestVersion, 'patch')))) {
baseVersion = npmLatestVersion;
}
console.log(`${releaseType} base version: ${baseVersion}`);
// Increment version
const nextVersion = semver.inc(baseVersion, releaseType, prereleaseName);
console.log(`New ${releaseType} version: ${nextVersion}`);
// Checkout new branch (lerna version requires this)
const branch = `release/${nextVersion}`;
await run(`git checkout -b ${branch}`);
// Update version in all packages
await run(`yarn lerna version --no-git-tag-version --yes ${nextVersion}`);
// Update yarn.lock with new package versions
await run(`YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install`);
// Update version in changelog (need to run in a package which has a version, so not the root package)
await run(`yarn workspace @lumx/core update-version-changelog`);
return { nextVersion, distTag, branch, releaseType, refName };
- name: "Build libs"
run: yarn build:libs
- name: "Publish version to NPM"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
DIST_TAG: ${{ fromJSON(steps.version.outputs.result).distTag }}
run: |
for package in $(echo packages/lumx-*);
do
(echo "Publishing $package"; cd $package/dist; npm publish --tag $DIST_TAG)
done
- name: "Git commit, tag & push"
if: ${{ fromJSON(steps.version.outputs.result).releaseType != 'prerelease' }}
id: git
run: |
git config --global user.name "github-actions"
git config --global user.email "[email protected]"
branch="${{ fromJSON(steps.version.outputs.result).branch }}"
echo "branch=$branch" >> $GITHUB_OUTPUT
tag="v${{ fromJSON(steps.version.outputs.result).nextVersion }}"
echo "tag=$tag" >> $GITHUB_OUTPUT
# Commit and push branch
commit="chore(release): release $tag"
echo "commit=$commit" >> $GITHUB_OUTPUT
git commit -am "$commit"
git push origin "$branch"
# TODO: need to a new git user to push tags
# Tag and push tag
#git tag "$tag"
#git push origin "$tag"
outputs:
releaseType: ${{ fromJSON(steps.version.outputs.result).releaseType }}
baseRef: ${{ fromJSON(steps.version.outputs.result).refName }}
commit: ${{ steps.git.outputs.commit }}
branch: ${{ steps.git.outputs.branch }}
versionTag: ${{ steps.git.outputs.tag }}
create_gh_pull_request:
if: ${{ needs.publish_version.outputs.releaseType != 'prerelease' }}
name: "Create pull request"
runs-on: ubuntu-latest
needs: [ publish_version ]
steps:
- name: "Create pull request"
uses: actions/github-script@v6
with:
script: |
github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '${{ needs.publish_version.outputs.commit }}',
head: '${{ needs.publish_version.outputs.branch }}',
base: '${{ needs.publish_version.outputs.baseRef }}',
body: 'https://github.com/lumapps/design-system/releases/tag/${{ needs.publish_version.outputs.versionTag }}\nTODO: `git tag ${{ needs.publish_version.outputs.versionTag }}` & `git push origin ${{ needs.publish_version.outputs.versionTag }}`',
draft: false,
});