Skip to content

Commit

Permalink
chore(ci): make upgrade-node workflow manually triggerable (#472)
Browse files Browse the repository at this point in the history
  • Loading branch information
xiehan authored Jan 14, 2025
1 parent f0ce2e8 commit b6f7115
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 54 deletions.
85 changes: 63 additions & 22 deletions .github/workflows/upgrade-node.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions projenrc/scripts/check-node-versions.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ async function getDesiredVersion() {

module.exports = async ({github, context, core}) => {
const version = await getDesiredVersion();
const short = version.match(versionRegex)[1];
const majorVersion = version.match(versionRegex)[1];

core.exportVariable('NEW_NODEJS_VERSION', version.slice(1)); // strip the 'v' from the start of the string
core.exportVariable('NEW_NODEJS_VERSION_SHORT', short);
core.exportVariable('NEW_NODEJS_VERSION_MAJOR', majorVersion);
}
137 changes: 107 additions & 30 deletions projenrc/upgrade-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { generateRandomCron } from "../src/util/random-cron";

/**
* Auto-updates Node to the next LTS version a month before the previous one goes EOL
* Can also be triggered manually with a hard-coded version of Node.js as input
*
* NOTE: This script is only used by cdktf-provider-project itself, not by the individual providers
*/
export class UpgradeNode {
Expand All @@ -22,25 +24,34 @@ export class UpgradeNode {
schedule: [
{ cron: generateRandomCron({ project, maxHour: 3, hourOffset: 2 }) },
],
workflowDispatch: {}, // allow manual triggering
workflowDispatch: {
inputs: {
version: {
description:
"Node.js version to upgrade to, in the format: 12.34.56",
required: false,
type: "string",
},
},
},
});

(workflow.concurrency as any) = {
group: "${{ github.workflow }}-${{ github.ref }}",
};

workflow.addJobs({
upgrade: {
name: "Upgrade Node.js",
version: {
name: "Determine version to upgrade to",
runsOn: ["ubuntu-latest"],
steps: [
{
name: "Checkout",
uses: "actions/checkout@v3",
uses: "actions/checkout",
},
{
name: "Setup Node.js",
uses: "actions/setup-node@v3",
uses: "actions/setup-node",
with: {
"node-version": project.minNodeVersion,
},
Expand All @@ -55,15 +66,17 @@ export class UpgradeNode {
run: [
`ENGINES_NODE_VERSION=$(npm pkg get engines.node | tr -d '"')`,
`CURRENT_VERSION=$(cut -d " " -f 2 <<< "$ENGINES_NODE_VERSION")`,
`CURRENT_VERSION_SHORT=$(cut -d "." -f 1 <<< "$CURRENT_VERSION")`,
`CURRENT_VERSION_MAJOR=$(cut -d "." -f 1 <<< "$CURRENT_VERSION")`,
`CURRENT_VERSION_MINOR=$(cut -d "." -f 2 <<< "$CURRENT_VERSION")`,
`echo "CURRENT_NODEJS_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV`,
`echo "CURRENT_NODEJS_VERSION_SHORT=$CURRENT_VERSION_SHORT" >> $GITHUB_ENV`,
`echo "CURRENT_NODEJS_VERSION_MAJOR=$CURRENT_VERSION_MAJOR" >> $GITHUB_ENV`,
`echo "CURRENT_NODEJS_VERSION_MINOR=$CURRENT_VERSION_MINOR" >> $GITHUB_ENV`,
`echo "value=$CURRENT_VERSION" >> $GITHUB_OUTPUT`,
`echo "short=$CURRENT_VERSION_SHORT" >> $GITHUB_OUTPUT`,
].join("\n"),
},
{
name: "Get the earliest supported Node.js version whose EOL date is at least a month away",
if: "${{ ! inputs.version }}",
uses: "actions/github-script@v6",
with: {
script: [
Expand All @@ -73,43 +86,106 @@ export class UpgradeNode {
},
},
{
name: "Set the new minNodeVersion in .projenrc.ts",
if: "env.CURRENT_NODEJS_VERSION_SHORT < env.NEW_NODEJS_VERSION_SHORT",
run: `sed -i "s/minNodeVersion: \\".*\\",/minNodeVersion: \\"$NEW_NODEJS_VERSION\\",/" ./.projenrc.ts`,
},
{
name: "Activate Projen to propagate the new version everywhere",
if: "env.CURRENT_NODEJS_VERSION_SHORT < env.NEW_NODEJS_VERSION_SHORT",
run: "yarn projen",
// In an ideal world this is where we'd validate that the manually-input version actually exists
// In practice, I couldn't figure out how to do this properly and it wasn't worth the effort
name: "Save the manually-input version to environment variables for comparison",
if: "${{ inputs.version }}",
env: {
NEW_VERSION: "${{ inputs.version }}",
},
run: [
`NEW_VERSION_MAJOR=$(cut -d "." -f 1 <<< "$NEW_VERSION")`,
`NEW_VERSION_MINOR=$(cut -d "." -f 2 <<< "$NEW_VERSION")`,
`echo "NEW_NODEJS_VERSION=$NEW_VERSION" >> $GITHUB_ENV`,
`echo "NEW_NODEJS_VERSION_MAJOR=$NEW_VERSION_MAJOR" >> $GITHUB_ENV`,
`echo "NEW_NODEJS_VERSION_MINOR=$NEW_VERSION_MINOR" >> $GITHUB_ENV`,
].join("\n"),
},
{
name: "Get values for pull request",
name: "Output env variables for use in the next job",
id: "latest_version",
if: "env.CURRENT_NODEJS_VERSION_SHORT < env.NEW_NODEJS_VERSION_SHORT",
run: [
`echo "value=$NEW_NODEJS_VERSION" >> $GITHUB_OUTPUT`,
`echo "short=$NEW_NODEJS_VERSION_SHORT" >> $GITHUB_OUTPUT`,
`echo "major=$NEW_NODEJS_VERSION_MAJOR" >> $GITHUB_OUTPUT`,
`[[ "$NEW_NODEJS_VERSION_MAJOR" > "$CURRENT_NODEJS_VERSION_MAJOR" || ("$NEW_NODEJS_VERSION_MAJOR" == "$CURRENT_NODEJS_VERSION_MAJOR" && "$NEW_NODEJS_VERSION_MINOR" > "$CURRENT_NODEJS_VERSION_MINOR") ]] && IS_NEWER=true`,
`echo "is_newer=$IS_NEWER" >> $GITHUB_OUTPUT`,
].join("\n"),
},
],
outputs: {
current: {
stepId: "current_version",
outputName: "value",
},
latest: {
stepId: "latest_version",
outputName: "value",
},
major: {
stepId: "latest_version",
outputName: "major",
},
should_upgrade: {
stepId: "latest_version",
outputName: "is_newer",
},
},
permissions: {
contents: JobPermission.READ,
},
},
upgrade: {
name: "Upgrade Node.js",
runsOn: ["ubuntu-latest"],
needs: ["version"],
if: "always() && needs.version.outputs.should_upgrade",
steps: [
{
name: "Checkout",
uses: "actions/checkout",
},
{
name: "Setup Node.js",
uses: "actions/setup-node",
with: {
"node-version": "${{ needs.version.outputs.latest }}",
},
},
{
name: "Install",
run: "yarn install",
},
{
name: "Set the new minNodeVersion in .projenrc.ts",
run: `sed -i "s/minNodeVersion: \\".*\\",/minNodeVersion: \\"$NEW_NODEJS_VERSION\\",/" ./.projenrc.ts`,
env: {
NEW_NODEJS_VERSION: "${{ needs.version.outputs.value }}",
},
},
{
name: "Activate Projen to propagate the new version everywhere",
run: "yarn projen",
env: {
CI: "false", // otherwise, `npx projen` will fail because it tries to update the lockfile
},
},
{
name: "Create Pull Request",
if: "env.CURRENT_NODEJS_VERSION_SHORT < env.NEW_NODEJS_VERSION_SHORT",
uses: "peter-evans/create-pull-request@v3",
uses: "peter-evans/create-pull-request",
with: {
"commit-message":
"chore!: increase minimum supported Node.js version to ${{ steps.latest_version.outputs.short }}",
branch:
"auto/upgrade-node-${{ steps.latest_version.outputs.short }}",
base: "main",
branch: "auto/upgrade-node-${{ needs.version.outputs.major }}",
"commit-message":
"chore!: increase minimum supported Node.js version to ${{ needs.version.outputs.major }} for this project only",
title:
"chore!: increase minimum supported Node.js version to ${{ steps.latest_version.outputs.short }}",
"chore!: increase minimum supported Node.js version to ${{ needs.version.outputs.major }} for this project only",
body: [
"This PR increases the minimum supported Node.js version",
"to `${{ steps.latest_version.outputs.value }}` from `${{ steps.current_version.outputs.value }}`",
"because version ${{ steps.current_version.outputs.short }} is less than 30 days away from EOL.",
"to `${{ needs.version.outputs.latest }}` from `${{ needs.version.outputs.current }}`",
"because version ${{ needs.version.outputs.current }} is less than 30 days away from EOL.",
"\n\nWhile this PR could be merged as-is, it is recommended that you scan the code (especially `.projenrc.ts`)",
"to see if there are any comments indicating changes that can/should be made when upgrading Node, such as:",
"\n```// The following line can be removed when upgrading to Node ${{ steps.latest_version.outputs.short }}```",
"\n```// The following line can be removed when upgrading to Node ${{ needs.version.outputs.major }}```",
].join(" "),
labels: "automerge,automated,security",
token: "${{ secrets.PROJEN_GITHUB_TOKEN }}",
Expand All @@ -121,7 +197,8 @@ export class UpgradeNode {
},
],
env: {
CI: "false", // otherwise, `npx projen` will fail because it tries to update the lockfile
CI: "true",
CHECKPOINT_DISABLE: "1",
},
permissions: {
contents: JobPermission.READ,
Expand Down

0 comments on commit b6f7115

Please # to comment.