mirror of
https://github.com/docker/build-push-action.git
synced 2025-08-09 18:12:12 +00:00
Merge pull request #118 from useblacksmith/builder-misconfig
fix: use correct platform when creating remote buildx builder
This commit is contained in:
commit
4fac79897d
99
.github/workflows/builder-platform-tests.yml
vendored
Normal file
99
.github/workflows/builder-platform-tests.yml
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
name: Builder platform matrix tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
# 1) Build AMD image on default (amd64) runner
|
||||
amd_on_amd:
|
||||
name: linux/amd64 build on blacksmith runner
|
||||
runs-on: blacksmith
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Write sample Dockerfile
|
||||
run: |
|
||||
cat <<'EOF' > Dockerfile
|
||||
FROM alpine:3.20
|
||||
# Install something non-trivial so that layer caching is observable
|
||||
RUN apk add --no-cache curl git
|
||||
EOF
|
||||
|
||||
- name: Build image (linux/amd64)
|
||||
uses: useblacksmith/build-push-action@builder-misconfig
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
push: false
|
||||
tags: test/amd_on_amd:${{ github.sha }}
|
||||
|
||||
# 2) Build ARM image on default (amd64) runner
|
||||
arm_on_amd:
|
||||
name: linux/arm64 build on blacksmith runner
|
||||
runs-on: blacksmith
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Write sample Dockerfile
|
||||
run: |
|
||||
cat <<'EOF' > Dockerfile
|
||||
FROM alpine:3.20
|
||||
RUN apk add --no-cache curl git
|
||||
EOF
|
||||
|
||||
- name: Build image (linux/arm64)
|
||||
uses: useblacksmith/build-push-action@builder-misconfig
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/arm64
|
||||
push: false
|
||||
tags: test/arm_on_amd:${{ github.sha }}
|
||||
|
||||
# 3) Build AMD image on ARM runner
|
||||
amd_on_arm:
|
||||
name: linux/amd64 build on blacksmith-arm runner
|
||||
runs-on: blacksmith-arm
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Write sample Dockerfile
|
||||
run: |
|
||||
cat <<'EOF' > Dockerfile
|
||||
FROM alpine:3.20
|
||||
RUN apk add --no-cache curl git
|
||||
EOF
|
||||
|
||||
- name: Build image (linux/amd64)
|
||||
uses: useblacksmith/build-push-action@builder-misconfig
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
push: false
|
||||
tags: test/amd_on_arm:${{ github.sha }}
|
||||
|
||||
# 4) Build ARM image on ARM runner
|
||||
arm_on_arm:
|
||||
name: linux/arm64 build on blacksmith-arm runner
|
||||
runs-on: blacksmith-arm
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Write sample Dockerfile
|
||||
run: |
|
||||
cat <<'EOF' > Dockerfile
|
||||
FROM alpine:3.20
|
||||
RUN apk add --no-cache curl git
|
||||
EOF
|
||||
|
||||
- name: Build image (linux/arm64)
|
||||
uses: useblacksmith/build-push-action@builder-misconfig
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/arm64
|
||||
push: false
|
||||
tags: test/arm_on_arm:${{ github.sha }}
|
2
dist/index.js
generated
vendored
2
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
984
package-lock.json
generated
984
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@babel/preset-env": "^7.27.2",
|
||||
"@babel/preset-typescript": "^7.27.0",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^20.12.12",
|
||||
|
@ -9,4 +9,4 @@ export class Metric {
|
||||
type: Metric_MetricType = Metric_MetricType.UNSPECIFIED;
|
||||
value: number = 0;
|
||||
labels: Record<string, string> = {};
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
export class StickyDiskService {
|
||||
constructor() {}
|
||||
|
||||
|
||||
async commitStickyDisk() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
async getStickyDisk() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
async queueDockerJob() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
async reportMetric() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
async up() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,4 +4,4 @@ export const execa = jest.fn().mockImplementation(() => {
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
};
|
||||
});
|
||||
});
|
||||
|
40
src/__tests__/remote-builder-args.test.ts
Normal file
40
src/__tests__/remote-builder-args.test.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import * as os from 'os';
|
||||
import {getRemoteBuilderArgs, resolveRemoteBuilderPlatforms} from '../context';
|
||||
|
||||
jest.mock('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
error: jest.fn()
|
||||
}));
|
||||
|
||||
describe('Remote builder platform argument resolution', () => {
|
||||
const builderName = 'test-builder';
|
||||
const builderUrl = 'tcp://127.0.0.1:1234';
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
test('returns comma-separated list when platforms are supplied', async () => {
|
||||
const platforms = ['linux/arm64', 'linux/amd64'];
|
||||
const platformStr = resolveRemoteBuilderPlatforms(platforms);
|
||||
expect(platformStr).toBe('linux/arm64,linux/amd64');
|
||||
|
||||
const args = await getRemoteBuilderArgs(builderName, builderUrl, platforms);
|
||||
const idx = args.indexOf('--platform');
|
||||
expect(idx).toBeGreaterThan(-1);
|
||||
expect(args[idx + 1]).toBe('linux/arm64,linux/amd64');
|
||||
});
|
||||
|
||||
test('falls back to host architecture when no platforms supplied', async () => {
|
||||
const platformStr = resolveRemoteBuilderPlatforms([]);
|
||||
const expectedPlatform = os.arch() === 'arm64' ? 'linux/arm64' : 'linux/amd64';
|
||||
expect(platformStr).toBe(expectedPlatform);
|
||||
|
||||
const args = await getRemoteBuilderArgs(builderName, builderUrl, []);
|
||||
const idx = args.indexOf('--platform');
|
||||
expect(idx).toBeGreaterThan(-1);
|
||||
expect(args[idx + 1]).toBe(expectedPlatform);
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as handlebars from 'handlebars';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
|
||||
import {Build} from '@docker/actions-toolkit/lib/buildx/build';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
||||
@ -336,12 +336,39 @@ export const tlsClientKeyPath = '/tmp/blacksmith_client_key.pem';
|
||||
export const tlsClientCaCertificatePath = '/tmp/blacksmith_client_ca_certificate.pem';
|
||||
export const tlsRootCaCertificatePath = '/tmp/blacksmith_root_ca_certificate.pem';
|
||||
|
||||
export async function getRemoteBuilderArgs(name: string, builderUrl: string): Promise<Array<string>> {
|
||||
/**
|
||||
* Resolve the platform list that should be passed to `docker buildx create`.
|
||||
*
|
||||
* Priority:
|
||||
* 1. Use the user-supplied platforms list (comma-joined) if provided.
|
||||
* 2. Fallback to the architecture of the host runner.
|
||||
*
|
||||
* The function is exported to allow isolated unit testing.
|
||||
*/
|
||||
export function resolveRemoteBuilderPlatforms(platforms?: string[]): string {
|
||||
// If user explicitly provided platforms, honour them verbatim.
|
||||
if (platforms && platforms.length > 0) {
|
||||
return platforms.join(',');
|
||||
}
|
||||
|
||||
// Otherwise derive from host architecture.
|
||||
const nodeArch = os.arch(); // e.g. 'x64', 'arm64', 'arm'
|
||||
const archMap: {[key: string]: string} = {
|
||||
x64: 'amd64',
|
||||
arm64: 'arm64',
|
||||
arm: 'arm'
|
||||
};
|
||||
const mappedArch = archMap[nodeArch] || nodeArch;
|
||||
return `linux/${mappedArch}`;
|
||||
}
|
||||
|
||||
export async function getRemoteBuilderArgs(name: string, builderUrl: string, platforms?: string[]): Promise<Array<string>> {
|
||||
const args: Array<string> = ['create', '--name', name, '--driver', 'remote'];
|
||||
|
||||
// TODO(aayush): Instead of hardcoding the platform, we should fail the build if the platform is
|
||||
// unsupported.
|
||||
args.push('--platform', 'linux/amd64');
|
||||
const platformFlag = resolveRemoteBuilderPlatforms(platforms);
|
||||
core.info(`Determined remote builder platform(s): ${platformFlag}`);
|
||||
args.push('--platform', platformFlag);
|
||||
|
||||
// Always use the remote builder, overriding whatever has been configured so far.
|
||||
args.push('--use');
|
||||
// Use the provided builder URL
|
||||
|
@ -202,7 +202,7 @@ actionsToolkit.run(
|
||||
if (builderInfo.addr) {
|
||||
await core.group(`Creating a builder instance`, async () => {
|
||||
const name = `blacksmith-${Date.now().toString(36)}`;
|
||||
const createCmd = await toolkit.buildx.getCommand(await context.getRemoteBuilderArgs(name, builderInfo.addr!));
|
||||
const createCmd = await toolkit.buildx.getCommand(await context.getRemoteBuilderArgs(name, builderInfo.addr!, inputs.platforms));
|
||||
core.info(`Creating builder with command: ${createCmd.command}`);
|
||||
await Exec.getExecOutput(createCmd.command, createCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
|
Loading…
x
Reference in New Issue
Block a user