Skip to content

Commit a276470

Browse files
Copilotneilime
andcommitted
Create build, lint, and test composite actions and update workflow
Co-authored-by: neilime <[email protected]>
1 parent 51c3404 commit a276470

File tree

7 files changed

+814
-125
lines changed

7 files changed

+814
-125
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 16 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -276,25 +276,12 @@ jobs:
276276
- run: |
277277
if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi
278278
if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi
279+
# jscpd:ignore-end
279280

280-
- id: setup-node
281-
if: inputs.container == ''
282-
uses: ./self-workflow/actions/setup-node
283-
with:
284-
working-directory: ${{ inputs.working-directory }}
285-
dependencies-cache: |
286-
nx
287-
prettier
288-
289-
- id: get-package-manager
290-
if: inputs.container
291-
uses: ./self-workflow/actions/get-package-manager
281+
- uses: ./self-workflow/actions/lint
292282
with:
293283
working-directory: ${{ inputs.working-directory }}
294-
# jscpd:ignore-end
295-
296-
- run: ${{ inputs.container && steps.get-package-manager.outputs.run-script-command || steps.setup-node.outputs.run-script-command }} lint
297-
working-directory: ${{ inputs.working-directory }}
284+
container: ${{ inputs.container != '' }}
298285

299286
build:
300287
name: 🏗️ Build
@@ -311,7 +298,7 @@ jobs:
311298
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
312299
id-token: write
313300
outputs:
314-
artifact-id: ${{ steps.build-artifact-id.outputs.artifact-id }}
301+
artifact-id: ${{ steps.build.outputs.artifact-id }}
315302
steps:
316303
- uses: hoverkraft-tech/ci-github-common/actions/checkout@5f11437c716059f30c635f90055060e4ef8b31a0 # 0.28.0
317304
if: needs.setup.outputs.build-commands && inputs.container == ''
@@ -333,79 +320,17 @@ jobs:
333320
if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi
334321
if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi
335322
# jscpd:ignore-end
336-
- if: needs.setup.outputs.build-commands
337-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
338-
env:
339-
BUILD_ENV: ${{ needs.setup.outputs.build-env }}
340-
BUILD_SECRETS: ${{ secrets.build-secrets }}
341-
with:
342-
script: |
343-
const envInput = process.env.BUILD_ENV || '{}';
344-
345-
let buildEnv = {};
346-
347-
try {
348-
buildEnv = JSON.parse(envInput);
349-
} catch (e) {
350-
core.setFailed(`Invalid build env JSON: ${e.message}`);
351-
}
352-
353-
for (const [key, value] of Object.entries(buildEnv)) {
354-
core.exportVariable(key, value);
355-
}
356-
357-
const secretsInput = process.env.BUILD_SECRETS || '';
358-
for (const line of secretsInput.split('\n').map(line => line.trim()).filter(Boolean)) {
359-
const [key, ...rest] = line.split('=');
360-
if (!key || !rest.length) {
361-
return core.setFailed(`Invalid build secrets format: ${line}`);
362-
}
363-
const value = rest.join('=');
364-
core.exportVariable(key.trim(), value.trim());
365-
}
366323

367-
- id: setup-node
368-
if: needs.setup.outputs.build-commands && inputs.container == ''
369-
uses: ./self-workflow/actions/setup-node
370-
with:
371-
working-directory: ${{ inputs.working-directory }}
372-
dependencies-cache: |
373-
nx
374-
gatsby
375-
storybook
376-
377-
- id: get-package-manager
378-
if: needs.setup.outputs.build-commands && inputs.container
379-
uses: ./self-workflow/actions/get-package-manager
324+
- id: build
325+
if: needs.setup.outputs.build-commands
326+
uses: ./self-workflow/actions/build
380327
with:
381328
working-directory: ${{ inputs.working-directory }}
382-
383-
- if: needs.setup.outputs.build-commands
384-
working-directory: ${{ inputs.working-directory }}
385-
env:
386-
BUILD_COMMANDS: ${{ needs.setup.outputs.build-commands }}
387-
RUN_SCRIPT_COMMAND: ${{ inputs.container && steps.get-package-manager.outputs.run-script-command || steps.setup-node.outputs.run-script-command }}
388-
run: |
389-
echo "$BUILD_COMMANDS" | while IFS= read -r COMMAND ; do
390-
# Trim whitespace
391-
COMMAND=$(echo "$COMMAND" | xargs)
392-
393-
# Skip empty lines
394-
if [ -z "$COMMAND" ]; then
395-
continue
396-
fi
397-
398-
echo -e "\n - Running $COMMAND"
399-
$RUN_SCRIPT_COMMAND "$COMMAND"
400-
done
401-
402-
- id: build-artifact-id
403-
if: needs.setup.outputs.build-commands && needs.setup.outputs.build-artifact
404-
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
405-
with:
406-
name: ${{ fromJSON(needs.setup.outputs.build-artifact).name }}
407-
path: ${{ fromJSON(needs.setup.outputs.build-artifact).paths }}
408-
if-no-files-found: error
329+
build-commands: ${{ needs.setup.outputs.build-commands }}
330+
build-env: ${{ needs.setup.outputs.build-env }}
331+
build-secrets: ${{ secrets.build-secrets }}
332+
build-artifact: ${{ needs.setup.outputs.build-artifact }}
333+
container: ${{ inputs.container != '' }}
409334

410335
test:
411336
name: 🧪 Test
@@ -422,6 +347,7 @@ jobs:
422347
contents: read
423348
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
424349
id-token: write
350+
pull-requests: write
425351
steps:
426352
- uses: hoverkraft-tech/ci-github-common/actions/checkout@5f11437c716059f30c635f90055060e4ef8b31a0 # 0.28.0
427353
if: inputs.container == ''
@@ -446,43 +372,8 @@ jobs:
446372
if [ -f .gitignore ]; then grep -q "self-workflow" .gitignore || echo "self-workflow" >> .gitignore; else echo "self-workflow" >> .gitignore; fi
447373
if [ -f .dockerignore ]; then grep -q "self-workflow" .dockerignore || echo "self-workflow" >> .dockerignore; else echo "self-workflow" >> .dockerignore; fi
448374
449-
- id: setup-node
450-
if: inputs.container == ''
451-
uses: ./self-workflow/actions/setup-node
375+
- uses: ./self-workflow/actions/test
452376
with:
453377
working-directory: ${{ inputs.working-directory }}
454-
dependencies-cache: |
455-
nx
456-
jest
457-
458-
- id: get-package-manager
459-
if: needs.setup.outputs.build-commands && inputs.container
460-
uses: ./self-workflow/actions/get-package-manager
461-
with:
462-
working-directory: ${{ inputs.working-directory }}
463-
464-
- run: ${{ inputs.container && steps.get-package-manager.outputs.run-script-command || steps.setup-node.outputs.run-script-command }} test:ci
465-
working-directory: ${{ inputs.working-directory }}
466-
env:
467-
CI: "true"
468-
469-
- if: inputs.coverage == 'codecov' && inputs.container
470-
env:
471-
REQUIRED_DEPS: |
472-
git
473-
curl
474-
gpg
475-
run: |
476-
apt-get update
477-
for dep in $REQUIRED_DEPS; do
478-
if ! dpkg -s "$dep" >/dev/null 2>&1; then
479-
apt-get install -y "$dep"
480-
fi
481-
done
482-
483-
- name: 📊 Code coverage
484-
if: inputs.coverage == 'codecov'
485-
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
486-
with:
487-
use_oidc: true
488-
disable_telem: true
378+
container: ${{ inputs.container != '' }}
379+
coverage: ${{ inputs.coverage }}

actions/build/README.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Build Action
2+
3+
Composite action to build Node.js projects with support for custom commands, environment variables, and artifact handling.
4+
5+
## Usage
6+
7+
```yaml
8+
- uses: hoverkraft-tech/ci-github-nodejs/actions/build@main
9+
with:
10+
# Working directory where build commands are executed
11+
# Default: "."
12+
working-directory: "."
13+
14+
# List of build commands to execute (npm/pnpm/yarn script names)
15+
# Required
16+
build-commands: |
17+
build
18+
compile
19+
20+
# JSON object of environment variables for the build
21+
# Default: "{}"
22+
build-env: |
23+
{
24+
"NODE_ENV": "production",
25+
"API_URL": "https://api.example.com"
26+
}
27+
28+
# Multi-line string of secrets in env format
29+
# Default: ""
30+
build-secrets: |
31+
SECRET_KEY=${{ secrets.SECRET_KEY }}
32+
API_TOKEN=${{ secrets.API_TOKEN }}
33+
34+
# JSON object for artifact upload configuration
35+
# Default: ""
36+
build-artifact: |
37+
{
38+
"name": "build-artifacts",
39+
"paths": "dist/\nbuild/"
40+
}
41+
42+
# Whether running in container mode (skips checkout and node setup)
43+
# Default: "false"
44+
container: "false"
45+
```
46+
47+
## Inputs
48+
49+
| Name | Description | Required | Default |
50+
| --------------------- | -------------------------------------------------------------------------------- | -------- | ------- |
51+
| `working-directory` | Working directory where build commands are executed | No | `.` |
52+
| `build-commands` | List of build commands to execute (npm/pnpm/yarn script names), one per line | Yes | - |
53+
| `build-env` | JSON object of environment variables to set during the build | No | `{}` |
54+
| `build-secrets` | Multi-line string of secrets in env format (KEY=VALUE) | No | `""` |
55+
| `build-artifact` | JSON object specifying artifact upload configuration | No | `""` |
56+
| `container` | Whether running in container mode (skips checkout and node setup) | No | `false` |
57+
58+
## Outputs
59+
60+
| Name | Description |
61+
| ------------- | ------------------------------------------------------ |
62+
| `artifact-id` | ID of the uploaded artifact (if artifact was specified) |
63+
64+
## Examples
65+
66+
### Basic build
67+
68+
```yaml
69+
- uses: hoverkraft-tech/ci-github-nodejs/actions/build@main
70+
with:
71+
build-commands: "build"
72+
```
73+
74+
### Build with artifact upload
75+
76+
```yaml
77+
- uses: hoverkraft-tech/ci-github-nodejs/actions/build@main
78+
with:
79+
build-commands: |
80+
build
81+
package
82+
build-artifact: |
83+
{
84+
"name": "build-output",
85+
"paths": "dist/"
86+
}
87+
```
88+
89+
### Build with environment variables and secrets
90+
91+
```yaml
92+
- uses: hoverkraft-tech/ci-github-nodejs/actions/build@main
93+
with:
94+
build-commands: "build"
95+
build-env: |
96+
{
97+
"NODE_ENV": "production",
98+
"API_URL": "https://api.example.com"
99+
}
100+
build-secrets: |
101+
SECRET_KEY=${{ secrets.SECRET_KEY }}
102+
```

0 commit comments

Comments
 (0)