diff --git a/.github/workflows/continuous-integration.md b/.github/workflows/continuous-integration.md index cff1a69..520fce8 100644 --- a/.github/workflows/continuous-integration.md +++ b/.github/workflows/continuous-integration.md @@ -3,7 +3,7 @@ # GitHub Reusable Workflow: Node.js Continuous Integration
- Node.js Continuous Integration + Node.js Continuous Integration
--- @@ -42,7 +42,7 @@ Workflow to performs continuous integration steps agains a Node.js project: ## Usage -```yaml +````yaml name: Node.js Continuous Integration on: push: @@ -54,9 +54,41 @@ permissions: id-token: write jobs: continuous-integration: - uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@6809332ced7647b3d52300a47d65657283f3395e # 0.16.0 + uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@36c861e31804957f2a85503b8aebe213f35b1235 # feat/continuous-intergration-build-secrets + secrets: + # Secrets to be used during the build step. + # Must be a multi-line env formatted string. + # Example: + # ```txt + # SECRET_EXAMPLE=$\{{ secrets.SECRET_EXAMPLE }} + # ``` + build-secrets: "" with: # Build parameters. Must be a string or a JSON object. + # For string, provide a list of commands to run during the build step, one per line. + # For JSON object, provide the following properties: + # + # - `commands`: Array of commands to run during the build step. + # - `env`: Object of environment variables to set during the build step. + # - `artifact`: String or array of strings specifying paths to artifacts to upload after the build + # + # Example: + # ```json + # { + # "commands": [ + # "build", + # "generate-artifacts" + # ], + # "env": { + # "CUSTOM_ENV_VAR": "value" + # }, + # "artifact": [ + # "dist/", + # "packages/package-a/build/" + # ] + # } + # ``` + # # Default: `build` build: build @@ -87,7 +119,7 @@ jobs: # Working directory where the dependencies are installed. # Default: `.` working-directory: . -``` +```` @@ -97,20 +129,39 @@ jobs: ### Workflow Call Inputs -| **Input** | **Description** | **Required** | **Type** | **Default** | -| ----------------------- | ----------------------------------------------------------------------------------------- | ------------ | ----------- | ------------ | -| **`build`** | Build parameters. Must be a string or a JSON object. | **false** | **string** | `build` | -| **`checks`** | Optional flag to enable check steps. | **false** | **boolean** | `true` | -| **`lint`** | Optional flag to enable linting. | **false** | **boolean** | `true` | -| **`code-ql`** | Code QL analysis language. See . | **false** | **string** | `typescript` | -| **`dependency-review`** | Enable dependency review scan. See . | **false** | **boolean** | `true` | -| **`test`** | Optional flag to enable test. | **false** | **boolean** | `true` | -| **`coverage`** | Specifify code coverage reporter. Supported values: `codecov`. | **false** | **string** | `codecov` | -| **`working-directory`** | Working directory where the dependencies are installed. | **false** | **string** | `.` | +| **Input** | **Description** | **Required** | **Type** | **Default** | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ----------- | ------------ | +| **`build`** | Build parameters. Must be a string or a JSON object. | **false** | **string** | `build` | +| | For string, provide a list of commands to run during the build step, one per line. | | | | +| | For JSON object, provide the following properties: | | | | +| | | | | | +| | - `commands`: Array of commands to run during the build step. | | | | +| | - `env`: Object of environment variables to set during the build step. | | | | +| | - `artifact`: String or array of strings specifying paths to artifacts to upload after the build | | | | +| | | | | | +| | Example: | | | | +| |
{
 "commands": [
 "build",
 "generate-artifacts"
 ],
 "env": {
 "CUSTOM_ENV_VAR": "value"
 },
 "artifact": [
 "dist/",
 "packages/package-a/build/"
 ]
}
| | | | +| **`checks`** | Optional flag to enable check steps. | **false** | **boolean** | `true` | +| **`lint`** | Optional flag to enable linting. | **false** | **boolean** | `true` | +| **`code-ql`** | Code QL analysis language. See . | **false** | **string** | `typescript` | +| **`dependency-review`** | Enable dependency review scan. See . | **false** | **boolean** | `true` | +| **`test`** | Optional flag to enable test. | **false** | **boolean** | `true` | +| **`coverage`** | Specifify code coverage reporter. Supported values: `codecov`. | **false** | **string** | `codecov` | +| **`working-directory`** | Working directory where the dependencies are installed. | **false** | **string** | `.` | + +## Secrets + +| **Secret** | **Description** | **Required** | +| ------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------ | +| **`build-secrets`** | Secrets to be used during the build step. | **false** | +| | Must be a multi-line env formatted string. | | +| | Example: | | +| |
SECRET_EXAMPLE=$\{{ secrets.SECRET_EXAMPLE }}
| | + @@ -133,7 +184,7 @@ on: jobs: continuous-integration: - uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@6809332ced7647b3d52300a47d65657283f3395e # 0.16.0 + uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@36c861e31804957f2a85503b8aebe213f35b1235 # feat/continuous-intergration-build-secrets permissions: id-token: write security-events: write diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 343a1f2..0fa2550 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -11,7 +11,31 @@ on: workflow_call: inputs: build: - description: Build parameters. Must be a string or a JSON object. + description: | + Build parameters. Must be a string or a JSON object. + For string, provide a list of commands to run during the build step, one per line. + For JSON object, provide the following properties: + + - `commands`: Array of commands to run during the build step. + - `env`: Object of environment variables to set during the build step. + - `artifact`: String or array of strings specifying paths to artifacts to upload after the build + + Example: + ```json + { + "commands": [ + "build", + "generate-artifacts" + ], + "env": { + "CUSTOM_ENV_VAR": "value" + }, + "artifact": [ + "dist/", + "packages/package-a/build/" + ] + } + ``` type: string required: false default: "build" @@ -50,6 +74,16 @@ on: type: string required: false default: "." + secrets: + build-secrets: + description: | + Secrets to be used during the build step. + Must be a multi-line env formatted string. + Example: + ```txt + SECRET_EXAMPLE=$\{{ secrets.SECRET_EXAMPLE }} + ``` + required: false permissions: contents: read @@ -89,6 +123,7 @@ jobs: contents: read id-token: write outputs: + build-env: ${{ steps.build-variables.outputs.env }} build-commands: ${{ steps.build-variables.outputs.commands }} build-artifact: ${{ steps.build-variables.outputs.artifact }} steps: @@ -122,6 +157,7 @@ jobs: const buildInput = `${{ inputs.build }}`.trim(); let commands = []; + let env = {}; // Build input can be json or string try { @@ -130,6 +166,7 @@ jobs: commands = build; } else { commands = build.commands ?? ["build"]; + env = build.env ?? {}; if (build.artifact) { if(typeof build.artifact === 'string') { @@ -159,6 +196,7 @@ jobs: } core.setOutput('commands', sanitizedCommands.join('\n')); + core.setOutput('env', JSON.stringify(env)); lint: name: 👕 Lint @@ -238,6 +276,37 @@ jobs: gatsby storybook + - if: needs.setup.outputs.build-commands + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + BUILD_ENV: ${{ needs.setup.outputs.build-env }} + BUILD_SECRETS: ${{ secrets.build-secrets }} + with: + script: | + const envInput = process.env.BUILD_ENV || '{}'; + + let buildEnv = {}; + + try { + buildEnv = JSON.parse(envInput); + } catch (e) { + core.setFailed(`Invalid build env JSON: ${e.message}`); + } + + for (const [key, value] of Object.entries(buildEnv)) { + core.exportVariable(key, value); + } + + const secretsInput = process.env.BUILD_SECRETS || ''; + for (const line of secretsInput.split('\n').map(line => line.trim()).filter(Boolean)) { + const [key, ...rest] = line.split('='); + if (!key || !rest.length) { + return core.setFailed(`Invalid build secrets format: ${line}`); + } + const value = rest.join('='); + core.exportVariable(key.trim(), value.trim()); + } + - if: needs.setup.outputs.build-commands working-directory: ${{ inputs.working-directory }} run: |