diff --git a/.github/workflows/upgrade-node.yml b/.github/workflows/upgrade-node.yml index 9797890..9e7bae0 100644 --- a/.github/workflows/upgrade-node.yml +++ b/.github/workflows/upgrade-node.yml @@ -4,17 +4,25 @@ name: upgrade-node on: schedule: - cron: 52 4 * * * - workflow_dispatch: {} + workflow_dispatch: + inputs: + version: + description: "Node.js version to upgrade to, in the format: 12.34.56" + required: false + type: string concurrency: group: ${{ github.workflow }}-${{ github.ref }} jobs: - upgrade: - name: Upgrade Node.js + version: + name: Determine version to upgrade to runs-on: ubuntu-latest permissions: contents: read - env: - CI: "false" + outputs: + current: ${{ steps.current_version.outputs.value }} + latest: ${{ steps.latest_version.outputs.value }} + major: ${{ steps.latest_version.outputs.major }} + should_upgrade: ${{ steps.latest_version.outputs.is_newer }} steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 @@ -29,42 +37,75 @@ jobs: 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 - name: Get the earliest supported Node.js version whose EOL date is at least a month away + if: ${{ ! inputs.version }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea with: script: |- const script = require('./projenrc/scripts/check-node-versions.js') await script({github, context, core}) + - 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 + - name: Output env variables for use in the next job + id: latest_version + run: |- + echo "value=$NEW_NODEJS_VERSION" >> $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 + upgrade: + name: Upgrade Node.js + needs: version + runs-on: ubuntu-latest + permissions: + contents: read + env: + CI: "true" + CHECKPOINT_DISABLE: "1" + if: always() && needs.version.outputs.should_upgrade + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - name: Setup Node.js + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af + with: + node-version: ${{ needs.version.outputs.latest }} + - name: Install + run: yarn install - name: Set the new minNodeVersion in .projenrc.ts - if: env.CURRENT_NODEJS_VERSION_SHORT < env.NEW_NODEJS_VERSION_SHORT + env: + NEW_NODEJS_VERSION: ${{ needs.version.outputs.value }} 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 + env: + CI: "false" run: yarn projen - - name: Get values for pull request - 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 - name: Create Pull Request - if: env.CURRENT_NODEJS_VERSION_SHORT < env.NEW_NODEJS_VERSION_SHORT uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f 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 - title: "chore!: increase minimum supported Node.js version to ${{ steps.latest_version.outputs.short }}" + 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 ${{ 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. + This PR increases the minimum supported Node.js version to `${{ needs.version.outputs.latest }}` from `${{ needs.version.outputs.current }}` because version ${{ needs.version.outputs.current }} is less than 30 days away from EOL. While 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: - ```// The following line can be removed when upgrading to Node ${{ steps.latest_version.outputs.short }}``` + ```// The following line can be removed when upgrading to Node ${{ needs.version.outputs.major }}``` labels: automerge,automated,security token: ${{ secrets.PROJEN_GITHUB_TOKEN }} author: team-tf-cdk diff --git a/projenrc/scripts/check-node-versions.js b/projenrc/scripts/check-node-versions.js old mode 100644 new mode 100755 index 83ed466..6046c7e --- a/projenrc/scripts/check-node-versions.js +++ b/projenrc/scripts/check-node-versions.js @@ -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); } diff --git a/projenrc/upgrade-node.ts b/projenrc/upgrade-node.ts index c278cba..72859ec 100644 --- a/projenrc/upgrade-node.ts +++ b/projenrc/upgrade-node.ts @@ -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 { @@ -22,7 +24,16 @@ 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) = { @@ -30,17 +41,17 @@ export class UpgradeNode { }; 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, }, @@ -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: [ @@ -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 }}", @@ -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,