bake: handle git auth token when parsing remote definition

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2024-04-12 10:08:14 +02:00
parent eb5663273f
commit 329c1c75cf
No known key found for this signature in database
GPG Key ID: ADE44D8C9D44FBE4
6 changed files with 52 additions and 11 deletions

View File

@ -15,6 +15,7 @@ on:
env: env:
NODE_VERSION: "20" NODE_VERSION: "20"
BUILDX_VERSION: "v0.14.0-rc1"
jobs: jobs:
test: test:
@ -102,6 +103,13 @@ jobs:
with: with:
node-version: ${{ env.NODE_VERSION }} node-version: ${{ env.NODE_VERSION }}
cache: 'yarn' cache: 'yarn'
-
name: Set up Docker Buildx
if: startsWith(matrix.os, 'ubuntu')
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
- -
name: Install name: Install
run: yarn install run: yarn install

View File

@ -35,14 +35,28 @@ maybe('getDefinition', () => {
[ [
'https://github.com/docker/buildx.git#v0.10.4', 'https://github.com/docker/buildx.git#v0.10.4',
['binaries-cross'], ['binaries-cross'],
path.join(fixturesDir, 'bake-buildx-0.10.4-binaries-cross.json') path.join(fixturesDir, 'bake-buildx-0.10.4-binaries-cross.json'),
false,
], ],
])('given %p', async (source: string, targets: string[], out: string) => { // TODO: uncomment this test case when we have access to the private repo using an access token
// [
// 'https://github.com/docker/test-docker-action.git#remote-private',
// ['default'],
// path.join(fixturesDir, 'bake-test-docker-action-remote-private.json'),
// true,
// ]
])('given %p', async (source: string, targets: string[], out: string, auth) => {
const gitAuthToken = process.env.GITHUB_TOKEN || '';
if (auth && !gitAuthToken) {
console.log(`Git auth token not available, skipping test`);
return;
}
const bake = new Bake(); const bake = new Bake();
const expectedDef = <BakeDefinition>JSON.parse(fs.readFileSync(out, {encoding: 'utf-8'}).trim()) const expectedDef = <BakeDefinition>JSON.parse(fs.readFileSync(out, {encoding: 'utf-8'}).trim())
expect(await bake.getDefinition({ expect(await bake.getDefinition({
source: source, source: source,
targets: targets targets: targets,
githubToken: gitAuthToken,
})).toEqual(expectedDef); })).toEqual(expectedDef);
}); });
}); });

View File

@ -0,0 +1,11 @@
{
"target": {
"default": {
"context": "https://github.com/docker/test-docker-action.git#remote-private",
"dockerfile": "Dockerfile",
"tags": [
"foo"
]
}
}
}

View File

@ -16,7 +16,7 @@
ARG NODE_VERSION=20 ARG NODE_VERSION=20
ARG DOCKER_VERSION=26.0.0 ARG DOCKER_VERSION=26.0.0
ARG BUILDX_VERSION=0.13.1 ARG BUILDX_VERSION=0.14.0-rc1
FROM node:${NODE_VERSION}-alpine AS base FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache cpio findutils git RUN apk add --no-cache cpio findutils git

View File

@ -36,6 +36,8 @@ export interface BakeCmdOpts {
sbom?: string; sbom?: string;
source?: string; source?: string;
targets?: Array<string>; targets?: Array<string>;
githubToken?: string; // for auth with remote definitions on private repos
} }
export class Bake { export class Bake {
@ -48,6 +50,13 @@ export class Bake {
public async getDefinition(cmdOpts: BakeCmdOpts, execOptions?: ExecOptions): Promise<BakeDefinition> { public async getDefinition(cmdOpts: BakeCmdOpts, execOptions?: ExecOptions): Promise<BakeDefinition> {
execOptions = execOptions || {ignoreReturnCode: true}; execOptions = execOptions || {ignoreReturnCode: true};
execOptions.ignoreReturnCode = true; execOptions.ignoreReturnCode = true;
if (cmdOpts.githubToken) {
execOptions.env = Object.assign({}, process.env, {
BUILDX_BAKE_GIT_AUTH_TOKEN: cmdOpts.githubToken
}) as {
[key: string]: string;
};
}
const args = ['bake']; const args = ['bake'];

View File

@ -77,24 +77,23 @@ export class Inputs {
} }
public static resolveBuildSecretString(kvp: string): string { public static resolveBuildSecretString(kvp: string): string {
return Inputs.resolveBuildSecret(kvp, false); const [key, file] = Inputs.resolveBuildSecret(kvp, false);
return `id=${key},src=${file}`;
} }
public static resolveBuildSecretFile(kvp: string): string { public static resolveBuildSecretFile(kvp: string): string {
return Inputs.resolveBuildSecret(kvp, true); const [key, file] = Inputs.resolveBuildSecret(kvp, true);
return `id=${key},src=${file}`;
} }
public static resolveBuildSecretEnv(kvp: string): string { public static resolveBuildSecretEnv(kvp: string): string {
const [key, value] = parseKvp(kvp); const [key, value] = parseKvp(kvp);
return `id=${key},env=${value}`; return `id=${key},env=${value}`;
} }
public static resolveBuildSecret(kvp: string, file: boolean): string { public static resolveBuildSecret(kvp: string, file: boolean): [string, string] {
const [key, _value] = parseKvp(kvp); const [key, _value] = parseKvp(kvp);
let value = _value; let value = _value;
if (file) { if (file) {
if (!fs.existsSync(value)) { if (!fs.existsSync(value)) {
throw new Error(`secret file ${value} not found`); throw new Error(`secret file ${value} not found`);
@ -103,7 +102,7 @@ export class Inputs {
} }
const secretFile = Context.tmpName({tmpdir: Context.tmpDir()}); const secretFile = Context.tmpName({tmpdir: Context.tmpDir()});
fs.writeFileSync(secretFile, value); fs.writeFileSync(secretFile, value);
return `id=${key},src=${secretFile}`; return [key, secretFile];
} }
public static getProvenanceInput(name: string): string { public static getProvenanceInput(name: string): string {