diff --git a/.github/actions/setup-ci/action.yml b/.github/actions/setup-ci/action.yml index 15a354f..ef0fcf6 100644 --- a/.github/actions/setup-ci/action.yml +++ b/.github/actions/setup-ci/action.yml @@ -12,11 +12,17 @@ inputs: runs: using: composite steps: + # Read the package's minimum supported runtime so CI validates the lowest common denominator. + - name: Read Required Node.JS Runtime + id: node-runtime + shell: bash + run: echo "runtime=$(node ./scripts/get-minimum-node-runtime.ts)" >> "$GITHUB_OUTPUT" + # Enable Node.JS in the build environment - name: Install - Node.JS Runtime uses: actions/setup-node@v6 with: - node-version: 24 + node-version: ${{ steps.node-runtime.outputs.runtime }} # Set up the socket firewall binary - name: Install - Socket Firewall diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index dd86c73..978a1c7 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -34,6 +34,9 @@ on: packageName: description: 'The name of the generated NPM package.' value: ${{ jobs.Build-Prod.outputs.packageName }} + nodeRuntime: + description: 'The Node.JS runtime version required by the project.' + value: ${{ jobs.Metadata.outputs.nodeRuntime }} # Define each session of execution that should be executed jobs: @@ -49,8 +52,8 @@ jobs: # Execute the workflow uses: ./.github/workflows/Metadata.yml with: - isRelease: ${{ github.event_name == 'workflow_call' && inputs.isRelease || false }} - isPrerelease: ${{ github.event_name == 'workflow_call' && inputs.isPrerelease || false }} + isRelease: ${{ inputs.isRelease || false }} + isPrerelease: ${{ inputs.isPrerelease || false }} # Execution session that builds the artifacts that are used for deployment Build-Prod: @@ -106,7 +109,7 @@ jobs: # Update the version of SHIELD being uploaded to have a different version number to avoid SDG version conflict - name: Tattoo Version - Experimental Channel if: ${{ needs.Metadata.outputs.channel != 'stable' }} - run: npm version --no-commit-hooks --no-git-tag-version "${{ needs.Metadata.outputs.version }}-${{ needs.Metadata.outputs.channel }}.${{ needs.Metadata.outputs.shortSha }}" + run: npm version --no-commit-hooks --no-git-tag-version "${{ needs.Metadata.outputs.semver }}" # Validate package integrity before publishing (tests, coverage, and production build). - name: Validate Package Before Publish diff --git a/.github/workflows/Metadata.yml b/.github/workflows/Metadata.yml index fbab80b..a090049 100644 --- a/.github/workflows/Metadata.yml +++ b/.github/workflows/Metadata.yml @@ -36,6 +36,12 @@ on: version: description: 'The version of the project that is being built.' value: ${{ jobs.Deploy-Metadata.outputs.version }} + semver: + description: 'The semantic version of the project that is being built.' + value: ${{ jobs.Deploy-Metadata.outputs.semver }} + nodeRuntime: + description: 'The Node.JS runtime version required by the project.' + value: ${{ jobs.Deploy-Metadata.outputs.nodeRuntime }} # Define each session of execution that should be executed jobs: @@ -58,6 +64,7 @@ jobs: environment: ${{ steps.computedGitHubEnvironment.outputs.environment }} shortSha: ${{ steps.shortSha.outputs.shortSha }} version: ${{ steps.computedVersion.outputs.version }} + nodeRuntime: ${{ steps.computedNodeRuntime.outputs.runtime }} # Set of actions to perform for this execution sandbox steps: @@ -65,6 +72,17 @@ jobs: - name: Checkout Files from Repo uses: actions/checkout@v7 + # Extract the minimum supported Node.JS runtime before setting it up. + - name: Extract Required Node.JS Runtime + id: computedNodeRuntime + run: echo "runtime=$(node ./scripts/get-minimum-node-runtime.ts)" >> "$GITHUB_OUTPUT" + + # Ensure npm commands run with the Node version required by the package. + - name: Set up Node.JS Runtime + uses: actions/setup-node@v7 + with: + node-version: ${{ steps.computedNodeRuntime.outputs.runtime }} + # Extract the project version from the package.json - name: Extract Project Version id: computedVersion @@ -84,17 +102,6 @@ jobs: echo "channel=alpha" >> "$GITHUB_OUTPUT" fi - # Compute the GitHub Environment to be used by the deployment - - name: Compute GitHub Environment - id: computedGitHubEnvironment - background: true - run: | - if [ "${{ github.event_name }}" = "release" ]; then - echo "environment=Azure-Privileged" >> "$GITHUB_OUTPUT" - else - echo "environment=Azure-Alpha" >> "$GITHUB_OUTPUT" - fi - # Get the first 7 chars of the SHA hash that represents the current commit that the build is operating off of. - name: Compute Short SHA - Experimental Channel id: shortSha @@ -104,3 +111,21 @@ jobs: # Bring job back to sync execution by awaiting for all async jobs to finish before continuing - name: Steps - Convert Back To Synchronous Execution wait-all: true + + # Concatenates all previous computed values to generate the semver + - name: Calculate Final Semver + id: semver + run: | + if [ "${{ steps.computedChannel.outputs.channel }}" != "stable" ]; then + echo "semver=${{ steps.computedVersion.outputs.version }}-${{ steps.computedChannel.outputs.channel }}.${{ steps.shortSha.outputs.shortSha }}" >> "$GITHUB_OUTPUT" + else + echo "semver=${{ steps.computedVersion.outputs.version }}" >> "$GITHUB_OUTPUT" + fi + + # Publish the resolved project version to the GitHub Actions job summary. + - name: Publish Metadata Summary + run: | + echo "## Build Metadata" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Project version: \`${{ steps.semver.outputs.semver }}\`" >> "$GITHUB_STEP_SUMMARY" + echo "Channel: \`${{ steps.computedChannel.outputs.channel }}\`" >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/Publish.yml b/.github/workflows/Publish.yml index c013e03..c0a1f1f 100644 --- a/.github/workflows/Publish.yml +++ b/.github/workflows/Publish.yml @@ -53,7 +53,7 @@ jobs: uses: actions/setup-node@v6 background: true with: - node-version: 24 + node-version: ${{ needs.Build.outputs.nodeRuntime }} # Download the compiled server binary - name: Download Artifact From Build Job diff --git a/.github/workflows/Security-Reachability.yml b/.github/workflows/Security-Reachability.yml index a6277d6..d2b3c2b 100644 --- a/.github/workflows/Security-Reachability.yml +++ b/.github/workflows/Security-Reachability.yml @@ -39,17 +39,21 @@ jobs: # Downloads the repo at the specified depth calculated previously - name: Clone Repo uses: actions/checkout@v7 - background: true with: # For PRs, fetch one additional commit for proper diff analysis fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }} + # Read the package's minimum supported runtime so CI validates the lowest common denominator. + - name: Read Required Node.JS Runtime + id: node-runtime + run: echo "runtime=$(node ./scripts/get-minimum-node-runtime.ts)" >> "$GITHUB_OUTPUT" + # Set up NodeJS on the build host with caching support to optimize execution - name: Set up Node.js uses: actions/setup-node@v6 background: true with: - node-version: 24 + node-version: ${{ steps.node-runtime.outputs.runtime }} # Set up Python runtime on the build host - name: Set up Python diff --git a/package-lock.json b/package-lock.json index cb387c0..0343403 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@software-hardware-integration-lab/log-engine", - "version": "0.0.6", + "version": "0.0.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@software-hardware-integration-lab/log-engine", - "version": "0.0.6", + "version": "0.0.7", "hasInstallScript": true, "dependencies": { "typia": "~12.1.1" diff --git a/package.json b/package.json index 2bbd790..c5a7266 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "0.0.6", + "version": "0.0.7", "name": "@software-hardware-integration-lab/log-engine", "description": "Logging engine with ability to add plugins for any destination", "author": { diff --git a/scripts/get-minimum-node-runtime.ts b/scripts/get-minimum-node-runtime.ts new file mode 100644 index 0000000..1b6cfdf --- /dev/null +++ b/scripts/get-minimum-node-runtime.ts @@ -0,0 +1,22 @@ +/* + * This script is used github workflows to ensure that they run on the minimum version + * allowed in the package JSON. This centralizes node version control. + */ + +import { readFileSync } from 'node:fs'; + +/** Gets the Node.JS runtime range declared by the package. */ +const runtimeRange = JSON.parse( + readFileSync(new URL('../package.json', import.meta.url), 'utf8') +).devEngines?.runtime?.version; +if (typeof runtimeRange !== 'string') { + throw new TypeError('package.json must declare devEngines.runtime.version.'); +} + +/** Gets the minimum complete semantic version within the declared range. */ +const minimumRuntime = runtimeRange.match(/\d+\.\d+\.\d+/)?.[0]; +if (!minimumRuntime) { + throw new TypeError(`Unable to determine a minimum Node.JS runtime from "${ runtimeRange }".`); +} + +process.stdout.write(minimumRuntime);