ci: Setup a semi-automated release process (no-changelog) (#5504)
* ci: Setup a semi-automated release process (no-changelog) * create tag/release before deleting the temporary branch
This commit is contained in:
committed by
GitHub
parent
5d74a2f89a
commit
3ae005cafe
52
.github/scripts/bump-versions.mjs
vendored
Normal file
52
.github/scripts/bump-versions.mjs
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import semver from 'semver';
|
||||
import { writeFile, readFile } from 'fs/promises';
|
||||
import { resolve } from 'path';
|
||||
import child_process from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
import assert from 'assert';
|
||||
|
||||
const exec = promisify(child_process.exec);
|
||||
|
||||
const rootDir = process.cwd();
|
||||
const releaseType = process.env.RELEASE_TYPE;
|
||||
assert.match(releaseType, /^(patch|minor|major)$/, 'Invalid RELEASE_TYPE');
|
||||
|
||||
// TODO: if releaseType is `auto` determine release type based on the changelog
|
||||
|
||||
const lastTag = (await exec('git describe --tags --match "n8n@*" --abbrev=0')).stdout.trim();
|
||||
const packages = JSON.parse((await exec('pnpm ls -r --only-projects --json')).stdout);
|
||||
|
||||
const packageMap = {};
|
||||
for (let { name, path, version, private: isPrivate, dependencies } of packages) {
|
||||
if (isPrivate && path !== rootDir) continue;
|
||||
if (path === rootDir) name = 'monorepo-root';
|
||||
|
||||
const isDirty = await exec(`git diff --quiet HEAD ${lastTag} -- ${path}`)
|
||||
.then(() => false)
|
||||
.catch((error) => true);
|
||||
|
||||
packageMap[name] = { path, isDirty, version };
|
||||
}
|
||||
|
||||
assert.ok(packageMap['n8n'].isDirty, 'No changes found since the last release');
|
||||
|
||||
// Keep the monorepo version up to date with the released version
|
||||
packageMap['monorepo-root'].version = packageMap['n8n'].version;
|
||||
|
||||
for (const packageName in packageMap) {
|
||||
const { path, version, isDirty } = packageMap[packageName];
|
||||
const packageFile = resolve(path, 'package.json');
|
||||
const packageJson = JSON.parse(await readFile(packageFile, 'utf-8'));
|
||||
|
||||
packageJson.version = packageMap[packageName].nextVersion =
|
||||
isDirty ||
|
||||
Object.keys(packageJson.dependencies).some(
|
||||
(dependencyName) => packageMap[dependencyName]?.isDirty,
|
||||
)
|
||||
? semver.inc(version, releaseType)
|
||||
: version;
|
||||
|
||||
await writeFile(packageFile, JSON.stringify(packageJson, null, 2) + '\n');
|
||||
}
|
||||
|
||||
console.log(packageMap['n8n'].nextVersion);
|
||||
6
.github/scripts/package.json
vendored
Normal file
6
.github/scripts/package.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"semver": "^7.3.8",
|
||||
"conventional-changelog-cli": "^2.2.2"
|
||||
}
|
||||
}
|
||||
2
.github/workflows/check-pr-title.yml
vendored
2
.github/workflows/check-pr-title.yml
vendored
@@ -6,6 +6,8 @@ on:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
branches:
|
||||
- '!release/*'
|
||||
|
||||
jobs:
|
||||
check-pr-title:
|
||||
|
||||
69
.github/workflows/release-create-pr.yml
vendored
Normal file
69
.github/workflows/release-create-pr.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: 'Release: Create Pull Request'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
base-branch:
|
||||
description: 'The branch to create this release PR from.'
|
||||
required: true
|
||||
default: 'master'
|
||||
|
||||
release-type:
|
||||
description: 'A SemVer release type.'
|
||||
required: true
|
||||
type: choice
|
||||
default: 'minor'
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
|
||||
jobs:
|
||||
create-release-pr:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.inputs.base-branch }}
|
||||
|
||||
- name: Push the base branch
|
||||
run: |
|
||||
git push -f origin ${{ github.event.inputs.base-branch }}:"release/${{ github.event.inputs.release-type }}"
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
- run: npm install --prefix=.github/scripts --no-package-lock
|
||||
|
||||
- name: Bump package versions
|
||||
run: |
|
||||
echo "NEXT_RELEASE=$(node .github/scripts/bump-versions.mjs)" >> $GITHUB_ENV
|
||||
pnpm i --lockfile-only
|
||||
env:
|
||||
RELEASE_TYPE: ${{ github.event.inputs.release-type }}
|
||||
|
||||
- name: Generate Changelog
|
||||
run: npx conventional-changelog-cli -p angular -i CHANGELOG.md -s -t n8n@
|
||||
|
||||
- name: Push the release branch, and Create the PR
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
base: 'release/${{ github.event.inputs.release-type }}'
|
||||
branch: 'release/${{ env.NEXT_RELEASE }}'
|
||||
commit-message: ':rocket: Release ${{ env.NEXT_RELEASE }}'
|
||||
delete-branch: true
|
||||
labels: 'release'
|
||||
title: ':rocket: Release ${{ env.NEXT_RELEASE }}'
|
||||
# 'TODO: add generated changelog to the body. create a script to generate custom changelog'
|
||||
body: ''
|
||||
|
||||
# TODO: post PR link to slack
|
||||
57
.github/workflows/release-publish.yml
vendored
Normal file
57
.github/workflows/release-publish.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: 'Release: Publish'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- 'release/patch'
|
||||
- 'release/minor'
|
||||
|
||||
jobs:
|
||||
publish-release:
|
||||
if: github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: 'pnpm'
|
||||
- run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
|
||||
- name: Publish to NPM
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
|
||||
pnpm publish -r --publish-branch ${{github.event.pull_request.base.ref}} --access public
|
||||
echo "RELEASE=$(node -e 'console.log(require("./package.json").version)')" >> $GITHUB_ENV
|
||||
|
||||
- name: Create Release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
commit: ${{github.event.pull_request.base.ref}}
|
||||
tag: 'n8n@${{env.RELEASE}}'
|
||||
|
||||
- name: Merge Release into 'master'
|
||||
run: |
|
||||
git fetch origin
|
||||
git checkout --track origin/master
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git merge --ff origin/${{github.event.pull_request.base.ref}}
|
||||
git push origin master
|
||||
git push origin :${{github.event.pull_request.base.ref}}
|
||||
Reference in New Issue
Block a user