Skip to content

Commit efeec95

Browse files
authored
Merge pull request #1505 from crazy-max/refactor-git-context
refactor: use new gitContext for build context resolution
2 parents ddf04b0 + 2d8f2a1 commit efeec95

File tree

8 files changed

+286
-78
lines changed

8 files changed

+286
-78
lines changed

.github/workflows/ci.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,57 @@ jobs:
101101
exit 1
102102
fi
103103
104+
git-context-query:
105+
runs-on: ubuntu-latest
106+
env:
107+
BUILDX_SEND_GIT_QUERY_AS_INPUT: true
108+
services:
109+
registry:
110+
image: registry:2.8.3@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373
111+
ports:
112+
- 5000:5000
113+
steps:
114+
-
115+
name: Checkout
116+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
117+
with:
118+
path: action
119+
-
120+
name: Set up QEMU
121+
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
122+
-
123+
name: Set up Docker Buildx
124+
id: buildx
125+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
126+
with:
127+
version: v0.29.0
128+
driver-opts: |
129+
network=host
130+
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
131+
-
132+
name: Build and push
133+
id: docker_build
134+
uses: ./action
135+
with:
136+
file: ./test/Dockerfile
137+
builder: ${{ steps.buildx.outputs.name }}
138+
platforms: linux/amd64,linux/arm64
139+
push: true
140+
tags: |
141+
localhost:5000/name/app:latest
142+
localhost:5000/name/app:1.0.0
143+
-
144+
name: Inspect
145+
run: |
146+
docker buildx imagetools inspect localhost:5000/name/app:1.0.0 --format '{{json .}}'
147+
-
148+
name: Check digest
149+
run: |
150+
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
151+
echo "::error::Digest should not be empty"
152+
exit 1
153+
fi
154+
104155
git-context-secret:
105156
runs-on: ubuntu-latest
106157
services:
@@ -394,6 +445,29 @@ jobs:
394445
MYSECRET=foo
395446
INVALID_SECRET=
396447
448+
secret-files:
449+
runs-on: ubuntu-latest
450+
steps:
451+
-
452+
name: Checkout
453+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
454+
-
455+
name: Set up Docker Buildx
456+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
457+
with:
458+
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
459+
driver-opts: |
460+
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
461+
-
462+
name: Build
463+
uses: ./
464+
with:
465+
context: .
466+
file: ./test/secret.Dockerfile
467+
secret-files: |
468+
MYSECRET=./test/secret.txt
469+
INVALID_SECRET=
470+
397471
secret-envs:
398472
runs-on: ubuntu-latest
399473
steps:

__tests__/context.test.ts

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
1212

1313
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder.js';
1414

15-
import * as context from '../src/context.js';
16-
1715
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'context-'));
1816
const tmpName = path.join(tmpDir, '.tmpname-vi');
1917
const fixturesDir = path.join(__dirname, 'fixtures');
@@ -52,6 +50,53 @@ vi.spyOn(Builder.prototype, 'inspect').mockImplementation(async (): Promise<Buil
5250
};
5351
});
5452

53+
describe('getInputs', () => {
54+
const originalEnv = process.env;
55+
56+
beforeEach(() => {
57+
process.env = Object.keys(process.env).reduce((object, key) => {
58+
if (!key.startsWith('INPUT_')) {
59+
object[key] = process.env[key];
60+
}
61+
return object;
62+
}, {});
63+
});
64+
65+
afterEach(() => {
66+
process.env = originalEnv;
67+
});
68+
69+
function setRequiredBooleanInputs(): void {
70+
setInput('load', 'false');
71+
setInput('no-cache', 'false');
72+
setInput('push', 'false');
73+
setInput('pull', 'false');
74+
}
75+
76+
test('uses Build git context when context input is empty', async () => {
77+
const gitContext = 'https://github.com/docker/build-push-action.git?ref=refs/heads/master';
78+
const gitContextSpy = vi.spyOn(Build.prototype, 'gitContext').mockResolvedValue(gitContext);
79+
setRequiredBooleanInputs();
80+
const context = await loadContextModule();
81+
const inputs = await context.getInputs();
82+
expect(inputs.context).toBe(gitContext);
83+
expect(gitContextSpy).toHaveBeenCalledTimes(1);
84+
gitContextSpy.mockRestore();
85+
});
86+
87+
test('renders defaultContext templates from Build git context', async () => {
88+
const gitContext = 'https://github.com/docker/build-push-action.git#refs/heads/master';
89+
const gitContextSpy = vi.spyOn(Build.prototype, 'gitContext').mockResolvedValue(gitContext);
90+
setRequiredBooleanInputs();
91+
setInput('context', '{{defaultContext}}:subdir');
92+
const context = await loadContextModule();
93+
const inputs = await context.getInputs();
94+
expect(inputs.context).toBe(`${gitContext}:subdir`);
95+
expect(gitContextSpy).toHaveBeenCalledTimes(1);
96+
gitContextSpy.mockRestore();
97+
});
98+
});
99+
55100
describe('getArgs', () => {
56101
const originalEnv = process.env;
57102
beforeEach(() => {
@@ -344,7 +389,7 @@ ccc`],
344389
'build',
345390
'--file', './test/Dockerfile',
346391
'--iidfile', imageIDFilePath,
347-
'--secret', `id=MY_SECRET,src=${tmpName}`,
392+
'--secret', `id=MY_SECRET,src=${path.join(fixturesDir, 'secret.txt')}`,
348393
'--builder', 'builder-git-context-2',
349394
'--network', 'host',
350395
'--push',
@@ -888,6 +933,46 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`]
888933
['GITHUB_SERVER_URL', 'https://github.cds.internal.unity3d.com'],
889934
])
890935
],
936+
[
937+
37,
938+
'0.29.0',
939+
new Map<string, string>([
940+
['load', 'false'],
941+
['no-cache', 'false'],
942+
['push', 'false'],
943+
['pull', 'false'],
944+
]),
945+
[
946+
'build',
947+
'--iidfile', imageIDFilePath,
948+
'--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
949+
'--metadata-file', metadataJson,
950+
'https://github.com/docker/build-push-action.git?ref=refs/heads/master'
951+
],
952+
new Map<string, string>([
953+
['BUILDX_SEND_GIT_QUERY_AS_INPUT', 'true']
954+
])
955+
],
956+
[
957+
38,
958+
'0.28.0',
959+
new Map<string, string>([
960+
['load', 'false'],
961+
['no-cache', 'false'],
962+
['push', 'false'],
963+
['pull', 'false'],
964+
]),
965+
[
966+
'build',
967+
'--iidfile', imageIDFilePath,
968+
'--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
969+
'--metadata-file', metadataJson,
970+
'https://github.com/docker/build-push-action.git#refs/heads/master'
971+
],
972+
new Map<string, string>([
973+
['BUILDX_SEND_GIT_QUERY_AS_INPUT', 'true']
974+
])
975+
],
891976
])(
892977
'[%d] given %o with %o as inputs, returns %o',
893978
async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>, envs: Map<string, string> | undefined) => {
@@ -903,6 +988,7 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`]
903988
vi.spyOn(Buildx.prototype, 'version').mockImplementation(async (): Promise<string> => {
904989
return buildxVersion;
905990
});
991+
const context = await loadContextModule();
906992
const inp = await context.getInputs();
907993
const res = await context.getArgs(inp, toolkit);
908994
expect(res).toEqual(expected);
@@ -918,3 +1004,8 @@ function getInputName(name: string): string {
9181004
function setInput(name: string, value: string): void {
9191005
process.env[getInputName(name)] = value;
9201006
}
1007+
1008+
async function loadContextModule(): Promise<typeof import('../src/context.js')> {
1009+
vi.resetModules();
1010+
return await import('../src/context.js');
1011+
}

dist/index.js

Lines changed: 29 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"packageManager": "yarn@4.9.2",
2525
"dependencies": {
2626
"@actions/core": "^3.0.0",
27-
"@docker/actions-toolkit": "0.79.0",
27+
"@docker/actions-toolkit": "0.87.0",
2828
"handlebars": "^4.7.9"
2929
},
3030
"devDependencies": {

src/context.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@ import * as core from '@actions/core';
22
import * as handlebars from 'handlebars';
33

44
import {Build} from '@docker/actions-toolkit/lib/buildx/build.js';
5-
import {Context} from '@docker/actions-toolkit/lib/context.js';
65
import {GitHub} from '@docker/actions-toolkit/lib/github/github.js';
76
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
87
import {Util} from '@docker/actions-toolkit/lib/util.js';
98

9+
let defaultContextPromise: Promise<string> | undefined;
10+
11+
async function getDefaultContext(): Promise<string> {
12+
defaultContextPromise ??= new Build().gitContext();
13+
return await defaultContextPromise;
14+
}
15+
1016
export interface Inputs {
1117
'add-hosts': string[];
1218
allow: string[];
@@ -44,6 +50,7 @@ export interface Inputs {
4450
}
4551

4652
export async function getInputs(): Promise<Inputs> {
53+
const defaultContext = await getDefaultContext();
4754
return {
4855
'add-hosts': Util.getInputList('add-hosts'),
4956
allow: Util.getInputList('allow'),
@@ -56,7 +63,7 @@ export async function getInputs(): Promise<Inputs> {
5663
'cache-to': Util.getInputList('cache-to', {ignoreComma: true}),
5764
call: core.getInput('call'),
5865
'cgroup-parent': core.getInput('cgroup-parent'),
59-
context: core.getInput('context') || Context.gitContext(),
66+
context: handlebars.compile(core.getInput('context'))({defaultContext}) || defaultContext,
6067
file: core.getInput('file'),
6168
labels: Util.getInputList('labels', {ignoreComma: true}),
6269
load: core.getBooleanInput('load'),
@@ -82,18 +89,17 @@ export async function getInputs(): Promise<Inputs> {
8289
}
8390

8491
export async function getArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
85-
const context = handlebars.compile(inputs.context)({
86-
defaultContext: Context.gitContext()
87-
});
8892
// prettier-ignore
8993
return [
90-
...await getBuildArgs(inputs, context, toolkit),
94+
...await getBuildArgs(inputs, inputs.context, toolkit),
9195
...await getCommonArgs(inputs, toolkit),
92-
context
96+
inputs.context
9397
];
9498
}
9599

96100
async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit): Promise<Array<string>> {
101+
const defaultContext = await getDefaultContext();
102+
97103
const args: Array<string> = ['build'];
98104
await Util.asyncForEach(inputs['add-hosts'], async addHost => {
99105
args.push('--add-host', addHost);
@@ -116,7 +122,7 @@ async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit):
116122
args.push(
117123
'--build-context',
118124
handlebars.compile(buildContext)({
119-
defaultContext: Context.gitContext()
125+
defaultContext: defaultContext
120126
})
121127
);
122128
});
@@ -182,7 +188,7 @@ async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit):
182188
core.warning(err.message);
183189
}
184190
});
185-
if (inputs['github-token'] && !Build.hasGitAuthTokenSecret(inputs.secrets) && context.startsWith(Context.gitContext())) {
191+
if (inputs['github-token'] && !Build.hasGitAuthTokenSecret(inputs.secrets) && context.startsWith(defaultContext)) {
186192
args.push('--secret', Build.resolveSecretString(`GIT_AUTH_TOKEN.${new URL(GitHub.serverURL).host.trimEnd()}=${inputs['github-token']}`));
187193
}
188194
if (inputs['shm-size']) {

test/secret.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo

0 commit comments

Comments
 (0)