Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions __tests__/buildx/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import * as rimraf from 'rimraf';

import {Context} from '../../src/context.js';
import {Build} from '../../src/buildx/build.js';
import {Buildx} from '../../src/buildx/buildx.js';

import {GitContextFormat} from '../../src/types/buildx/build.js';

const fixturesDir = path.join(__dirname, '..', '.fixtures');
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'buildx-build-'));
Expand All @@ -41,6 +44,57 @@ afterEach(() => {
rimraf.sync(tmpDir);
});

describe('gitContext', () => {
const originalEnv = process.env;
beforeEach(() => {
vi.resetModules();
process.env = {
...originalEnv,
DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF: '',
BUILDX_SEND_GIT_QUERY_AS_INPUT: ''
};
});
afterEach(() => {
process.env = originalEnv;
});
// prettier-ignore
test.each([
// no format set (defaults to fragment)
['refs/heads/master', undefined, false, false, true, 'https://github.com/docker/actions-toolkit.git#860c1904a1ce19322e91ac35af1ab07466440c37'],
['master', undefined, false, false, true, 'https://github.com/docker/actions-toolkit.git#860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', undefined, false, false, true, 'https://github.com/docker/actions-toolkit.git#refs/pull/15/merge'],
['refs/tags/v1.0.0', undefined, false, false, true, 'https://github.com/docker/actions-toolkit.git#860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', undefined, true, false, true, 'https://github.com/docker/actions-toolkit.git#refs/pull/15/head'],
// no format set (defaults to query only when client-side query resolution is enabled and supported)
['refs/heads/master', undefined, false, true, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/heads/master&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', undefined, false, true, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/pull/15/merge&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', undefined, true, true, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/pull/15/head&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/heads/master', undefined, false, true, false, 'https://github.com/docker/actions-toolkit.git#860c1904a1ce19322e91ac35af1ab07466440c37'],
// query format
['refs/heads/master', 'query', false, false, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/heads/master&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
['master', 'query', false, false, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/heads/master&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', 'query', false, false, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/pull/15/merge&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/tags/v1.0.0', 'query', false, false, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/tags/v1.0.0&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', 'query', true, false, true, 'https://github.com/docker/actions-toolkit.git?ref=refs/pull/15/head&checksum=860c1904a1ce19322e91ac35af1ab07466440c37'],
// fragment format
['refs/heads/master', 'fragment', false, false, true, 'https://github.com/docker/actions-toolkit.git#860c1904a1ce19322e91ac35af1ab07466440c37'],
['master', 'fragment', false, false, true, 'https://github.com/docker/actions-toolkit.git#860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', 'fragment', false, false, true, 'https://github.com/docker/actions-toolkit.git#refs/pull/15/merge'],
['refs/tags/v1.0.0', 'fragment', false, false, true, 'https://github.com/docker/actions-toolkit.git#860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', 'fragment', true, false, true, 'https://github.com/docker/actions-toolkit.git#refs/pull/15/head'],
])(
'given %o and %o, should return %o',
async (ref: string, format: string | undefined, prHeadRef: boolean, sendGitQueryAsInput: boolean, buildxQuerySupport: boolean, expected: string) => {
process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF = prHeadRef ? 'true' : '';
process.env.BUILDX_SEND_GIT_QUERY_AS_INPUT = sendGitQueryAsInput ? 'true' : '';
const buildx = new Buildx();
vi.spyOn(buildx, 'versionSatisfies').mockResolvedValue(buildxQuerySupport);
const build = new Build({buildx});
expect(await build.gitContext(ref, '860c1904a1ce19322e91ac35af1ab07466440c37', format as GitContextFormat)).toEqual(expected);
}
);
});

describe('resolveImageID', () => {
it('matches', async () => {
const imageID = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
Expand Down
64 changes: 21 additions & 43 deletions __tests__/context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import {describe, expect, vi, it, afterEach, beforeEach, test} from 'vitest';
import {describe, expect, it, afterEach} from 'vitest';
import fs from 'fs';
import os from 'os';
import path from 'path';
Expand All @@ -23,57 +23,35 @@ import * as rimraf from 'rimraf';
import {Context} from '../src/context.js';

const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'context-'));
const tmpName = path.join(tmpDir, '.tmpname-vi');

vi.spyOn(Context, 'tmpDir').mockImplementation((): string => {
fs.mkdirSync(tmpDir, {recursive: true});
return tmpDir;
});

vi.spyOn(Context, 'tmpName').mockImplementation((): string => {
return tmpName;
});

afterEach(() => {
rimraf.sync(tmpDir);
fs.mkdirSync(tmpDir, {recursive: true});
});

describe('gitRef', () => {
it('returns refs/heads/master', async () => {
expect(Context.gitRef()).toEqual('refs/heads/master');
describe('tmpDir', () => {
it('returns an existing directory and keeps it stable', () => {
const dir = Context.tmpDir();
expect(fs.existsSync(dir)).toBe(true);
expect(fs.statSync(dir).isDirectory()).toBe(true);
expect(Context.tmpDir()).toEqual(dir);
});
});

describe('parseGitRef', () => {
const originalEnv = process.env;
beforeEach(() => {
vi.resetModules();
process.env = {
...originalEnv,
DOCKER_GIT_CONTEXT_PR_HEAD_REF: ''
};
});
afterEach(() => {
process.env = originalEnv;
describe('tmpName', () => {
it('returns a path for the provided tmpdir and template', () => {
const name = Context.tmpName({
tmpdir: tmpDir,
template: '.tmpname-XXXXXX'
});
expect(path.dirname(name)).toEqual(tmpDir);
expect(path.basename(name)).toMatch(/^\.tmpname-/);
expect(fs.existsSync(name)).toBe(false);
});
// prettier-ignore
test.each([
['refs/heads/master', '860c1904a1ce19322e91ac35af1ab07466440c37', false, '860c1904a1ce19322e91ac35af1ab07466440c37'],
['master', '860c1904a1ce19322e91ac35af1ab07466440c37', false, '860c1904a1ce19322e91ac35af1ab07466440c37'],
['refs/pull/15/merge', '860c1904a1ce19322e91ac35af1ab07466440c37', false, 'refs/pull/15/merge'],
['refs/heads/master', '', false, 'refs/heads/master'],
['master', '', false, 'master'],
['refs/tags/v1.0.0', '', false, 'refs/tags/v1.0.0'],
['refs/pull/15/merge', '', false, 'refs/pull/15/merge'],
['refs/pull/15/merge', '', true, 'refs/pull/15/head'],
])('given %o and %o, should return %o', async (ref: string, sha: string, prHeadRef: boolean, expected: string) => {
process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF = prHeadRef ? 'true' : '';
expect(Context.parseGitRef(ref, sha)).toEqual(expected);
});
});

describe('gitContext', () => {
it('returns refs/heads/master', async () => {
expect(Context.gitContext()).toEqual('https://github.com/docker/actions-toolkit.git#refs/heads/master');
it('returns different paths on consecutive calls', () => {
const first = Context.tmpName({tmpdir: tmpDir, template: '.tmpname-XXXXXX'});
const second = Context.tmpName({tmpdir: tmpDir, template: '.tmpname-XXXXXX'});
expect(first).not.toEqual(second);
});
});
37 changes: 36 additions & 1 deletion src/buildx/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
import fs from 'fs';
import path from 'path';
import * as core from '@actions/core';
import * as github from '@actions/github';
import {parse} from 'csv-parse/sync';

import {Buildx} from './buildx.js';
import {Context} from '../context.js';
import {GitHub} from '../github/github.js';
import {Util} from '../util.js';

import {BuildMetadata} from '../types/buildx/build.js';
import {BuildMetadata, GitContextFormat} from '../types/buildx/build.js';
import {VertexWarning} from '../types/buildkit/client.js';
import {ProvenancePredicate} from '../types/intoto/slsa_provenance/v0.2/provenance.js';

Expand All @@ -48,6 +49,40 @@ export class Build {
this.metadataFilename = `build-metadata-${Util.generateRandomString()}.json`;
}

public async gitContext(ref?: string, sha?: string, format?: GitContextFormat): Promise<string> {
const setPullRequestHeadRef: boolean = !!(process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF && process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF === 'true');
ref = ref || github.context.ref;
sha = sha || github.context.sha;
if (!ref.startsWith('refs/')) {
ref = `refs/heads/${ref}`;
} else if (ref.startsWith(`refs/pull/`) && setPullRequestHeadRef) {
ref = ref.replace(/\/merge$/g, '/head');
}
const baseURL = `${GitHub.serverURL}/${github.context.repo.owner}/${github.context.repo.repo}.git`;
if (!format) {
let sendGitQueryAsInput = false;
if (process.env.BUILDX_SEND_GIT_QUERY_AS_INPUT) {
try {
sendGitQueryAsInput = Util.parseBool(process.env.BUILDX_SEND_GIT_QUERY_AS_INPUT);
} catch {
sendGitQueryAsInput = false;
}
}
if (sendGitQueryAsInput && (await this.buildx.versionSatisfies('>=0.29.0'))) {
format = 'query';
} else {
format = 'fragment';
}
}
if (format === 'query') {
return `${baseURL}?ref=${ref}${sha !== '' ? `&checksum=${sha}` : ''}`;
}
if (sha && !ref.startsWith(`refs/pull/`)) {
return `${baseURL}#${sha}`;
}
return `${baseURL}#${ref}`;
}

public getImageIDFilePath(): string {
return path.join(Context.tmpDir(), this.iidFilename);
}
Expand Down
24 changes: 0 additions & 24 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ import fs from 'fs';
import os from 'os';
import path from 'path';
import * as tmp from 'tmp';
import * as github from '@actions/github';

import {GitHub} from './github/github.js';

export class Context {
private static readonly _tmpDir = fs.mkdtempSync(path.join(Context.ensureDirExists(process.env.RUNNER_TEMP || os.tmpdir()), 'docker-actions-toolkit-'));
Expand All @@ -37,25 +34,4 @@ export class Context {
public static tmpName(options?: tmp.TmpNameOptions): string {
return tmp.tmpNameSync(options);
}

public static gitRef(): string {
return Context.parseGitRef(github.context.ref, github.context.sha);
}

public static parseGitRef(ref: string, sha: string): string {
const setPullRequestHeadRef: boolean = !!(process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF && process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF === 'true');
if (sha && ref && !ref.startsWith('refs/')) {
ref = `refs/heads/${ref}`;
}
if (sha && !ref.startsWith(`refs/pull/`)) {
ref = sha;
} else if (ref.startsWith(`refs/pull/`) && setPullRequestHeadRef) {
ref = ref.replace(/\/merge$/g, '/head');
}
return ref;
}

public static gitContext(): string {
return `${GitHub.serverURL}/${github.context.repo.owner}/${github.context.repo.repo}.git#${Context.gitRef()}`;
}
}
2 changes: 2 additions & 0 deletions src/types/buildx/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

export type GitContextFormat = 'fragment' | 'query';

export type BuildMetadata = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
Expand Down
Loading