Merge pull request #403 from crazy-max/buildx-fix-localstate

buildx: fix broken local state
This commit is contained in:
CrazyMax 2024-07-05 16:02:45 +02:00 committed by GitHub
commit e49e07d23e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 109 additions and 5 deletions

View File

@ -24,7 +24,7 @@ import {Buildx} from '../../src/buildx/buildx';
import {Context} from '../../src/context'; import {Context} from '../../src/context';
import {Exec} from '../../src/exec'; import {Exec} from '../../src/exec';
import {Cert} from '../../src/types/buildx/buildx'; import {Cert, LocalState} from '../../src/types/buildx/buildx';
const fixturesDir = path.join(__dirname, '..', 'fixtures'); const fixturesDir = path.join(__dirname, '..', 'fixtures');
// prettier-ignore // prettier-ignore
@ -250,19 +250,70 @@ describe('resolveCertsDriverOpts', () => {
}); });
}); });
describe('localState', () => {
// prettier-ignore
test.each([
[
'default/default/ij71n3ubmhck85d03zdvye5nr',
{
LocalPath: '/home/crazymax/github/docker_org/buildx',
DockerfilePath: '/home/crazymax/github/docker_org/buildx/Dockerfile'
} as LocalState,
],
[
'default/default/7pnnqpgacnqq98oa1a1h5sz6t',
{
LocalPath: 'https://github.com/docker/actions-toolkit.git#:__tests__/fixtures',
DockerfilePath: 'hello.Dockerfile'
} as LocalState,
],
[
'default/default/84p2qpgacnqq98oa1a1h5sz6t',
{
LocalPath: 'https://github.com/docker/actions-toolkit.git#:__tests__/fixtures',
DockerfilePath: '-'
} as LocalState,
],
[
'default/default/a5s9rlg9cnqq98oa1a1h5sz6t',
{
LocalPath: '-',
DockerfilePath: ''
} as LocalState,
],
[
'default/default/aav2ix4nw5eky66fw045dkylr',
{
LocalPath: 'https://github.com/docker/buildx.git',
DockerfilePath: ''
} as LocalState,
],
[
'default/default/w38vcd5fo5cfvfyig77qjec0v',
{
LocalPath: '/home/crazy/hello',
DockerfilePath: '-'
} as LocalState,
]
])('given %p', async (ref: string, expected: LocalState) => {
const localState = Buildx.localState(path.join(fixturesDir, 'buildx-refs'), ref);
expect(localState).toEqual(expected);
});
});
describe('refs', () => { describe('refs', () => {
it('returns all refs', async () => { it('returns all refs', async () => {
const refs = Buildx.refs({ const refs = Buildx.refs({
dir: path.join(fixturesDir, 'buildx-refs') dir: path.join(fixturesDir, 'buildx-refs')
}); });
expect(Object.keys(refs).length).toEqual(11); expect(Object.keys(refs).length).toEqual(16);
}); });
it('returns default builder refs', async () => { it('returns default builder refs', async () => {
const refs = Buildx.refs({ const refs = Buildx.refs({
dir: path.join(fixturesDir, 'buildx-refs'), dir: path.join(fixturesDir, 'buildx-refs'),
builderName: 'default' builderName: 'default'
}); });
expect(Object.keys(refs).length).toEqual(8); expect(Object.keys(refs).length).toEqual(13);
}); });
it('returns foo builder refs', async () => { it('returns foo builder refs', async () => {
const refs = Buildx.refs({ const refs = Buildx.refs({
@ -281,6 +332,6 @@ describe('refs', () => {
builderName: 'default', builderName: 'default',
since: new Date('2024-01-10T00:00:00Z') since: new Date('2024-01-10T00:00:00Z')
}); });
expect(Object.keys(refs).length).toEqual(5); expect(Object.keys(refs).length).toEqual(10);
}); });
}); });

View File

@ -0,0 +1 @@
{"LocalPath":"/home/crazy/foo/bar/https:/github.com/docker/actions-toolkit.git#:__tests__/fixtures","DockerfilePath":"/home/crazy/foo/bar/hello.Dockerfile"}

View File

@ -0,0 +1 @@
{"LocalPath":"/home/crazy/foo/bar/https:/github.com/docker/actions-toolkit.git#:__tests__/fixtures","DockerfilePath":"/home/crazy/foo/bar/-"}

View File

@ -0,0 +1 @@
{"LocalPath":"/home/crazy/foo/bar/-","DockerfilePath":""}

View File

@ -0,0 +1 @@
{"LocalPath":"/home/crazy/foo/bar/https:/github.com/docker/buildx.git","DockerfilePath":""}

View File

@ -0,0 +1 @@
{"LocalPath":"/home/crazy/hello","DockerfilePath":"/home/crazy/hello/-"}

View File

@ -177,6 +177,54 @@ export class Buildx {
return driverOpts; return driverOpts;
} }
public static localState(dir: string, ref: string): LocalState {
const [builderName, nodeName, id] = ref.split('/');
if (!builderName || !nodeName || !id) {
throw new Error(`Invalid build reference: ${ref}`);
}
const lsPath = path.join(dir, builderName, nodeName, id);
if (!fs.existsSync(lsPath)) {
throw new Error(`Local state not found in ${lsPath}`);
}
return Buildx.fixLocalState(<LocalState>JSON.parse(fs.readFileSync(lsPath, 'utf8')));
}
// https://github.com/docker/buildx/pull/2560
private static fixLocalState(ls: LocalState): LocalState {
const fnTrimToValidContext = function (inp: string): [string, string, boolean] {
const match = inp.match(/(.*)(https?:\/{1,2}\S+|ssh:\/\/\S+|git:\/\/\S+)/i);
if (match && match.length == 3) {
const trimed = match[1];
let url = match[2];
if (url.startsWith('https:/') && !url.startsWith('https://')) {
url = url.replace('https:/', 'https://');
}
if (url.startsWith('http:/') && !url.startsWith('http://')) {
url = url.replace('http:/', 'http://');
}
if (url.startsWith('ssh:/') && !url.startsWith('ssh://')) {
url = url.replace('https:/', 'ssh://');
}
if (url.startsWith('git:/') && !url.startsWith('git://')) {
url = url.replace('https:/', 'git://');
}
return [url, trimed, true];
}
return [inp, '', false];
};
const [contextPath, trimedPath, isURL] = fnTrimToValidContext(ls.LocalPath);
if (isURL) {
ls.LocalPath = contextPath;
if (ls.DockerfilePath.indexOf(trimedPath) === 0) {
ls.DockerfilePath = ls.DockerfilePath.substring(trimedPath.length);
}
}
ls.LocalPath = ls.LocalPath.endsWith('/-') ? '-' : ls.LocalPath;
ls.DockerfilePath = ls.DockerfilePath.endsWith('/-') ? '-' : ls.DockerfilePath;
return ls;
}
public static refs(opts: LocalRefsOpts, refs: LocalRefsResponse = {}): LocalRefsResponse { public static refs(opts: LocalRefsOpts, refs: LocalRefsResponse = {}): LocalRefsResponse {
const {dir, builderName, nodeName, since} = opts; const {dir, builderName, nodeName, since} = opts;
@ -210,7 +258,7 @@ export class Buildx {
if (since && stat.mtime < since) { if (since && stat.mtime < since) {
continue; continue;
} }
const localState = <LocalState>JSON.parse(fs.readFileSync(filePath, 'utf8')); const localState = Buildx.fixLocalState(<LocalState>JSON.parse(fs.readFileSync(filePath, 'utf8')));
const ref = `${builderName}/${nodeName}/${file}`; const ref = `${builderName}/${nodeName}/${file}`;
refs[ref] = localState; refs[ref] = localState;
} }