Skip to content

Commit e4455fe

Browse files
Copilotneilime
andcommitted
Add support for all container options in continuous-integration workflow
Co-authored-by: neilime <[email protected]>
1 parent eccc7ed commit e4455fe

File tree

1 file changed

+104
-22
lines changed

1 file changed

+104
-22
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 104 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,33 @@ on:
8383
required: false
8484
default: "."
8585
container:
86-
description: "Docker container image to run CI steps in. When specified, steps will execute inside this container instead of checking out code. The container should have the project code and dependencies pre-installed."
86+
description: |
87+
Container configuration to run CI steps in.
88+
Accepts either a string (container image name) or a JSON object with container options.
89+
90+
String format (simple):
91+
```
92+
container: "node:18"
93+
```
94+
95+
JSON object format (advanced):
96+
```json
97+
{
98+
"image": "node:18",
99+
"env": {
100+
"NODE_ENV": "production"
101+
},
102+
"ports": [8080],
103+
"volumes": ["/tmp:/tmp"],
104+
"options": "--cpus 2"
105+
}
106+
```
107+
108+
All properties from GitHub's container specification are supported except credentials (use secrets instead).
109+
See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/run-jobs-in-a-container
110+
111+
When specified, steps will execute inside this container instead of checking out code.
112+
The container should have the project code and dependencies pre-installed.
87113
type: string
88114
required: false
89115
default: ""
@@ -105,6 +131,67 @@ on:
105131
permissions: {}
106132

107133
jobs:
134+
parse-container:
135+
name: 📦 Parse Container Configuration
136+
if: inputs.container != ''
137+
runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
138+
permissions: {}
139+
outputs:
140+
config: ${{ steps.parse.outputs.config }}
141+
steps:
142+
- id: parse
143+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
144+
env:
145+
CONTAINER_INPUT: ${{ inputs.container }}
146+
with:
147+
script: |
148+
const containerInput = process.env.CONTAINER_INPUT.trim();
149+
150+
// Check if input is a JSON object or a simple string
151+
const isJson = containerInput.startsWith('{');
152+
153+
let config = {
154+
image: '',
155+
options: '--user root:root'
156+
};
157+
158+
if (isJson) {
159+
try {
160+
const container = JSON.parse(containerInput);
161+
162+
// Set image
163+
config.image = container.image || '';
164+
165+
// Add env if provided
166+
if (container.env && Object.keys(container.env).length > 0) {
167+
config.env = container.env;
168+
}
169+
170+
// Add ports if provided
171+
if (container.ports && container.ports.length > 0) {
172+
config.ports = container.ports;
173+
}
174+
175+
// Add volumes if provided
176+
if (container.volumes && container.volumes.length > 0) {
177+
config.volumes = container.volumes;
178+
}
179+
180+
// Merge user options with default --user root:root
181+
if (container.options) {
182+
config.options = `${config.options} ${container.options}`;
183+
}
184+
} catch (error) {
185+
core.setFailed(`Failed to parse container input as JSON: ${error.message}`);
186+
return;
187+
}
188+
} else {
189+
// Simple string format - just the image name
190+
config.image = containerInput;
191+
}
192+
193+
core.setOutput('config', JSON.stringify(config));
194+
108195
code-ql:
109196
name: 🛡️ CodeQL Analysis
110197
if: inputs.checks == true && inputs.code-ql != ''
@@ -131,10 +218,9 @@ jobs:
131218
setup:
132219
name: ⚙️ Setup
133220
runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
134-
container:
135-
image: ${{ inputs.container != '' && inputs.container || null }}
136-
# Root user is required to use GitHub Actions features inside the container
137-
options: --user root:root
221+
container: ${{ inputs.container != '' && fromJSON(needs.parse-container.outputs.config) || null }}
222+
needs: parse-container
223+
if: ${{ always() && !cancelled() && !failure() }}
138224
permissions:
139225
contents: read
140226
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
@@ -248,13 +334,12 @@ jobs:
248334
249335
lint:
250336
name: 👕 Lint
251-
if: inputs.checks == true && inputs.lint
337+
if: inputs.checks == true && inputs.lint && always() && !cancelled() && !failure()
252338
runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
253-
container:
254-
image: ${{ inputs.container != '' && inputs.container || null }}
255-
# Root user is required to use GitHub Actions features inside the container
256-
options: --user root:root
257-
needs: setup
339+
container: ${{ inputs.container != '' && fromJSON(needs.parse-container.outputs.config) || null }}
340+
needs:
341+
- parse-container
342+
- setup
258343
# jscpd:ignore-start
259344
permissions:
260345
contents: read
@@ -304,14 +389,13 @@ jobs:
304389

305390
build:
306391
name: 🏗️ Build
307-
if: inputs.checks == true
392+
if: inputs.checks == true && always() && !cancelled() && !failure()
308393
runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
309394
# jscpd:ignore-start
310-
container:
311-
image: ${{ inputs.container != '' && inputs.container || null }}
312-
# Root user is required to use GitHub Actions features inside the container
313-
options: --user root:root
314-
needs: setup
395+
container: ${{ inputs.container != '' && fromJSON(needs.parse-container.outputs.config) || null }}
396+
needs:
397+
- parse-container
398+
- setup
315399
permissions:
316400
contents: read
317401
# FIXME: This is a workaround for having workflow ref. See https://github.com/orgs/community/discussions/38659
@@ -352,13 +436,11 @@ jobs:
352436

353437
test:
354438
name: 🧪 Test
355-
if: inputs.checks == true && inputs.test
439+
if: inputs.checks == true && inputs.test && always() && !cancelled() && !failure()
356440
runs-on: ${{ inputs.runs-on && fromJson(inputs.runs-on) || 'ubuntu-latest' }}
357-
container:
358-
image: ${{ inputs.container != '' && inputs.container || null }}
359-
# Root user is required to use GitHub Actions features inside the container
360-
options: --user root:root
441+
container: ${{ inputs.container != '' && fromJSON(needs.parse-container.outputs.config) || null }}
361442
needs:
443+
- parse-container
362444
- setup
363445
- build
364446
permissions:

0 commit comments

Comments
 (0)