feat: move over to some of the publishing methods from backstage/backstage

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam 2024-04-17 09:16:38 +02:00
parent 6b95674af4
commit 34bea9a33a
3 changed files with 154 additions and 65 deletions

View File

@ -7,8 +7,16 @@ on:
description: "Name of the Workspace"
required: true
type: string
force_release:
description: "Force release even if no changesets are present"
required: false
type: boolean
workflow_call:
inputs:
force_release:
description: "Force release even if no changesets are present"
required: false
type: boolean
workspace:
description: "Name of the Workspace"
required: true
@ -28,7 +36,7 @@ jobs:
CI: true
NODE_OPTIONS: --max-old-space-size=4096
outputs:
publishing-needed: ${{ steps.should-publish.outputs.out }}
needs_release: ${{ steps.release_check.outputs.needs_release }}
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
@ -65,16 +73,20 @@ jobs:
# TODO(vinzscam): If we use secrets.GITHUB_TOKEN here, checks won't trigger in the version packages
# PR. cf. https://github.community/t/push-doesnt-trigger-workflow-action-in-an-open-pr/118675
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Early check whether publishing is needed
id: should-publish
if: steps.changesets-pr.outputs.hasChangesets == 'false'
run: echo "out=$(node ../../scripts/ci/publishing-needed.js ${{ inputs.workspace }})" >> $GITHUB_OUTPUT
- name: Check if release
id: release_check
if: inputs.force_release != true
run: node scripts/ci/check-if-release.js
env:
WORKSPACE_NAME: ${{ inputs.workspace }}
COMMIT_SHA_BEFORE: '${{ github.event.before }}'
release:
name: Release workspace ${{ inputs.workspace }}
runs-on: ubuntu-latest
needs: changesets-pr
if: needs.changesets-pr.outputs.publishing-needed
if: needs.changesets-pr.outputs.needs_release == 'true' || inputs.force_release == true
defaults:
run:
working-directory: ./workspaces/${{ inputs.workspace }}
@ -111,15 +123,9 @@ jobs:
- name: Build all packages
run: yarn build:all
- name: Publish packages
id: changesets-publish
uses: changesets/action@v1
with:
publish: yarn workspaces foreach npm publish --access public
title: Version Packages (${{ inputs.workspace }})
cwd: workspaces/${{ inputs.workspace }}
version: yarn changeset version
- name: publish
run: |
yarn config set -H 'npmAuthToken' "${{secrets.NPM_TOKEN}}"
yarn workspaces foreach -v --no-private npm publish --access public --tolerate-republish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,132 @@
#!/usr/bin/env node
/* eslint-disable @backstage/no-undeclared-imports */
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// This script is used to determine whether a particular commit has changes
// that should lead to a release. It is run as part of the main master build
// to determine whether the release flow should be run as well.
//
// It has the following output which can be used later in GitHub actions:
//
// needs_release = 'true' | 'false'
const { execFile: execFileCb } = require('child_process');
const { resolve: resolvePath } = require('path');
const { promises: fs } = require('fs');
const { promisify } = require('util');
const { EOL } = require('os');
const parentRef = process.env.COMMIT_SHA_BEFORE || 'HEAD^';
const execFile = promisify(execFileCb);
async function runPlain(cmd, ...args) {
try {
const { stdout } = await execFile(cmd, args, { shell: true });
return stdout.trim();
} catch (error) {
if (error.stderr) {
process.stderr.write(error.stderr);
}
if (!error.code) {
throw error;
}
throw new Error(
`Command '${[cmd, ...args].join(' ')}' failed with code ${error.code}`,
);
}
}
async function main() {
if (!process.env.WORKSPACE_NAME) {
throw new Error('WORKSPACE_NAME environment variable not set');
}
process.cwd(resolvePath(__dirname, '..', '..', 'workspaces', process.env.WORKSPACE_NAME));
if (!process.env.GITHUB_OUTPUT) {
throw new Error('GITHUB_OUTPUT environment variable not set');
}
const diff = await runPlain(
'git',
'diff',
'--name-only',
parentRef,
"'*/package.json'", // Git treats this as what would usually be **/package.json
);
const packageList = diff
.split('\n')
.filter(path => path.match(/^(packages|plugins)\/[^/]+\/package\.json$/));
const packageVersions = await Promise.all(
packageList.map(async path => {
let name;
let newVersion;
let oldVersion;
try {
const data = JSON.parse(
await runPlain('git', 'show', `${parentRef}:${path}`),
);
name = data.name;
oldVersion = data.version;
} catch {
oldVersion = '<none>';
}
try {
const data = JSON.parse(await fs.readFile(path, 'utf8'));
name = data.name;
newVersion = data.version;
} catch (error) {
if (error.code === 'ENOENT') {
newVersion = '<none>';
}
}
return { name, oldVersion, newVersion };
}),
);
const newVersions = packageVersions.filter(
({ oldVersion, newVersion }) =>
oldVersion !== newVersion &&
oldVersion !== '<none>' &&
newVersion !== '<none>',
);
if (newVersions.length === 0) {
console.log('No package version bumps detected, no release needed');
await fs.appendFile(process.env.GITHUB_OUTPUT, `needs_release=false${EOL}`);
return;
}
console.log('Package version bumps detected, a new release is needed');
const maxLength = Math.max(...newVersions.map(_ => _.name.length));
for (const { name, oldVersion, newVersion } of newVersions) {
console.log(
` ${name.padEnd(maxLength, ' ')} ${oldVersion} to ${newVersion}`,
);
}
await fs.appendFile(process.env.GITHUB_OUTPUT, `needs_release=true${EOL}`);
}
main().catch(error => {
console.error(error.stack);
process.exit(1);
});

View File

@ -1,49 +0,0 @@
import path, { dirname } from "path";
import fs from "fs/promises";
import { spawnSync } from "child_process";
import { fileURLToPath } from "url";
if (process.argv.length !== 3) {
throw new Error(`Usage: node publishing-needed.js <name-of-the-workspace>`);
}
const workspace = process.argv[2];
(async function main() {
const pluginsFolderPath = path.join(
dirname(fileURLToPath(import.meta.url)),
"..",
"..",
"workspaces",
workspace,
"plugins"
);
const packagesToBePublished = [];
const plugins = await fs.readdir(pluginsFolderPath, { withFileTypes: true });
for (const plugin of plugins) {
if (!plugin.isDirectory()) {
continue;
}
const packageJson = JSON.parse(
await fs.readFile(
path.join(pluginsFolderPath, plugin.name, "package.json"),
"utf-8"
)
);
const nameAndVersion = `${packageJson.name}@${packageJson.version}`;
const result = spawnSync("npm", ["show", nameAndVersion]);
if (result.status !== 0) {
// package is missing
packagesToBePublished.push(nameAndVersion);
}
}
if (packagesToBePublished.length === 0) {
console.log(false);
}
console.log(true);
})().catch((error) => {
console.error(error.stack);
process.exit(1);
});