Skip to content

Commit b7a3986

Browse files
committed
distribute: pin dependencies and sanitize inputs
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent 5f34045 commit b7a3986

File tree

1 file changed

+73
-36
lines changed

1 file changed

+73
-36
lines changed

.github/workflows/distribute.yml

Lines changed: 73 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,12 @@ on:
8484
type: boolean
8585
description: "Do not use cache when building the image"
8686
required: false
87+
default: false
8788
bake-pull:
8889
type: boolean
8990
description: "Always attempt to pull a newer version of the image"
9091
required: false
92+
default: false
9193
bake-provenance:
9294
type: string
9395
description: "Provenance is a shorthand for --set=*.attest=type=provenance"
@@ -108,73 +110,100 @@ on:
108110
description: "API token used to authenticate to a Git repository for remote definitions"
109111
required: false
110112

113+
env:
114+
ACTIONS_TOOLKIT_VERSION: "0.54.0"
115+
HANDLEBARS_VERSION: "4.7.8"
116+
111117
jobs:
112118
prepare:
113119
runs-on: ubuntu-latest
114120
outputs:
115121
includes: ${{ steps.set.outputs.includes }}
116122
steps:
123+
-
124+
name: Install npm dependencies
125+
uses: actions/github-script@v7
126+
with:
127+
script: |
128+
await exec.exec('npm', ['install',
129+
'@docker/actions-toolkit@${{ env.ACTIONS_TOOLKIT_VERSION }}',
130+
'handlebars@${{ env.HANDLEBARS_VERSION }}'
131+
]);
117132
-
118133
name: Set includes
119134
id: set
120135
uses: actions/github-script@v7
136+
env:
137+
INPUT_RUNNER: ${{ inputs.runner }}
138+
INPUT_TARGET: ${{ inputs.target }}
139+
INPUT_META-IMAGE: ${{ inputs.meta-image }}
140+
INPUT_BAKE-ALLOW: ${{ inputs.bake-allow }}
141+
INPUT_BAKE-FILES: ${{ inputs.bake-files }}
142+
INPUT_BAKE-NO-CACHE: ${{ inputs.bake-no-cache }}
143+
INPUT_BAKE-PROVENANCE: ${{ inputs.bake-provenance }}
144+
INPUT_BAKE-SBOM: ${{ inputs.bake-sbom }}
145+
INPUT_BAKE-SET: ${{ inputs.bake-set }}
146+
INPUT_BAKE-SOURCE: ${{ inputs.bake-source }}
147+
GITHUB_TOKEN: ${{ secrets.github-token || github.token }}
121148
with:
122149
script: |
123-
let def;
124-
const files = `${{ inputs.bake-files }}` ? `${{ inputs.bake-files }}`.split(/[\r?\n,]+/).filter(Boolean) : [];
125-
const target = `${{ inputs.target }}`;
150+
const handlebars = require('handlebars');
151+
const { Bake } = require('@docker/actions-toolkit/lib/buildx/bake');
152+
const { Build } = require('@docker/actions-toolkit/lib/buildx/build');
153+
const { Context } = require('@docker/actions-toolkit/lib/context');
154+
const { Util } = require('@docker/actions-toolkit/lib/util');
126155
127-
const metaImage = `${{ inputs.meta-image }}` ? `${{ inputs.meta-image }}`.split(/[\r?\n,]+/).filter(Boolean) : [];
128-
if (metaImage.length > 1) {
156+
if (Util.getInputList('meta-image').length > 1) {
129157
throw new Error('Only one meta-image is allowed');
130158
}
131159
132-
await core.group(`Install npm dependencies`, async () => {
133-
await exec.exec('npm', ['install', '@docker/actions-toolkit', 'handlebars']);
160+
const inpRunner = core.getInput('runner');
161+
const inpTarget = core.getInput('target');
162+
const inpBakeAllow = Util.getInputList('bake-allow');
163+
const inpBakeFiles = Util.getInputList('bake-files');
164+
const inpBakeNoCache = core.getBooleanInput('bake-no-cache');
165+
const inpBakeProvenance = Build.getProvenanceInput('bake-provenance');
166+
const inpBakeSbom = core.getInput('bake-sbom');
167+
const inpBakeSet = Util.getInputList('bake-set', {ignoreComma: true, quote: false});
168+
let inpBakeSource = handlebars.compile(core.getInput('source'))({
169+
defaultContext: Context.gitContext()
134170
});
171+
if (!inpBakeSource) {
172+
inpBakeSource = Context.gitContext();
173+
}
174+
if (inpBakeSource === '.') {
175+
inpBakeSource = '';
176+
}
135177
178+
let def;
136179
await core.group(`Validating definition`, async () => {
137-
const handlebars = require('handlebars');
138-
const { Context } = require('@docker/actions-toolkit/lib/context');
139-
const { Bake } = require('@docker/actions-toolkit/lib/buildx/bake');
140-
141-
let source = handlebars.compile(`${{ inputs.bake-source }}`)({
142-
defaultContext: Context.gitContext()
143-
});
144-
if (!source) {
145-
source = Context.gitContext();
146-
}
147-
if (source === '.') {
148-
source = '';
149-
}
150-
151180
const bake = new Bake();
152181
def = await bake.getDefinition({
153-
allow: `${{ inputs.bake-allow }}` ? `${{ inputs.bake-allow }}`.split(/[\r?\n,]+/).filter(Boolean) : [],
154-
files: `${{ inputs.bake-files }}` ? `${{ inputs.bake-files }}`.split(/[\r?\n,]+/).filter(Boolean) : [],
155-
noCache: ${{ inputs.bake-no-cache }},
156-
overrides: `${{ inputs.bake-set }}` ? `${{ inputs.bake-set }}`.split(/[\r?\n,]+/).filter(Boolean) : [],
157-
provenance: `${{ inputs.bake-provenance }}`,
158-
sbom: `${{ inputs.bake-sbom }}`,
159-
source: source,
160-
targets: [`${{ inputs.target }}`],
161-
githubToken: `${{ secrets.github-token || github.token }}`
182+
allow: inpBakeAllow,
183+
files: inpBakeFiles,
184+
noCache: inpBakeNoCache,
185+
overrides: inpBakeSet,
186+
provenance: inpBakeProvenance,
187+
sbom: inpBakeSbom,
188+
source: inpBakeSource,
189+
targets: [inpTarget],
190+
githubToken: process.env.GITHUB_TOKEN
162191
});
163192
if (!def) {
164193
throw new Error('Bake definition not set');
165194
}
166195
});
167196
168197
await core.group(`Set includes`, async () => {
169-
const platforms = def.target[target].platforms;
198+
const platforms = def.target[inpTarget].platforms;
170199
if (platforms.length > 100) {
171200
throw new Error('Too many platforms');
172201
} else if (platforms.length <= 1) {
173202
throw new Error('At least 2 platforms are required');
174203
}
175204
let includes = [];
176205
platforms.forEach((platform, index) => {
177-
let runner = `${{ inputs.runner }}`;
206+
let runner = inpRunner;
178207
if (runner === 'auto') {
179208
runner = platform.startsWith('linux/arm') ? 'ubuntu-24.04-arm' : 'ubuntu-latest';
180209
}
@@ -353,10 +382,12 @@ jobs:
353382
name: Set digest output
354383
id: digest
355384
uses: actions/github-script@v7
385+
env:
386+
INPUT_TARGET: ${{ inputs.target }}
356387
with:
357388
script: |
358389
const metadata = JSON.parse(`${{ steps.bake.outputs.metadata }}`);
359-
const digest = metadata[`${{ inputs.target }}`]['containerimage.digest'];
390+
const digest = metadata[core.getInput('target')]['containerimage.digest'];
360391
const outputKey = `digest_${{ matrix.index }}`;
361392
core.info(`Setting digest output: ${outputKey}=${digest}`);
362393
core.setOutput(outputKey, digest);
@@ -392,8 +423,14 @@ jobs:
392423
-
393424
name: Create manifest list
394425
uses: actions/github-script@v7
426+
env:
427+
INPUT_PUSH: ${{ inputs.push }}
428+
INPUT_META-IMAGE: ${{ inputs.meta-image }}
395429
with:
396430
script: |
431+
const inpPush = core.getBooleanInput('push');
432+
const inpMetaImage = core.getInput('meta-image');
433+
397434
let digests = [];
398435
await core.group(`Digests`, async () => {
399436
digests = Object.values(JSON.parse(`${{ toJSON(needs.build.outputs) }}`));
@@ -411,10 +448,10 @@ jobs:
411448
createArgs.push(`-t`, tag);
412449
}
413450
for (const digest of digests) {
414-
createArgs.push(`${{ inputs.meta-image }}@${digest}`);
451+
createArgs.push(`${inpMetaImage}@${digest}`);
415452
}
416453
417-
if (${{ inputs.push }}) {
454+
if (inpPush) {
418455
if (tags.length === 0) {
419456
throw new Error('No tags to create manifest list');
420457
}
@@ -426,7 +463,7 @@ jobs:
426463
}
427464
});
428465
await core.group(`Inspect image`, async () => {
429-
await exec.getExecOutput('docker', ['buildx', 'imagetools', 'inspect', `${{ inputs.meta-image }}:${tags[0]}`], {
466+
await exec.getExecOutput('docker', ['buildx', 'imagetools', 'inspect', `${inpMetaImage}:${tags[0]}`], {
430467
ignoreReturnCode: true
431468
}).then(res => {
432469
if (res.stderr.length > 0 && res.exitCode != 0) {

0 commit comments

Comments
 (0)