mirror of
https://github.com/docker/build-push-action.git
synced 2025-06-13 22:57:12 +02:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
41a004098f | |||
41b2c888ba | |||
72350a828e | |||
5f6cd6b99d | |||
bef45c0027 | |||
c8e09bfd16 | |||
b3b0ca3523 | |||
0307a522bb | |||
8616d520af | |||
21692b9878 | |||
fc7e9a2b38 |
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
15
.github/CONTRIBUTING.md
vendored
15
.github/CONTRIBUTING.md
vendored
@ -15,6 +15,21 @@ Contributions to this project are [released](https://help.github.com/articles/gi
|
||||
7. Push to your fork and [submit a pull request](https://github.com/docker/build-push-action/compare)
|
||||
8. Pat your self on the back and wait for your pull request to be reviewed and merged.
|
||||
|
||||
## Container based developer flow
|
||||
|
||||
If you don't want to maintain a Node developer environment that fits this project you can use containerized commands instead of invoking yarn directly.
|
||||
|
||||
```
|
||||
# format code and build javascript artifacts
|
||||
docker buildx bake pre-checkin
|
||||
|
||||
# validate all code has correctly formatted and built
|
||||
docker buildx bake validate
|
||||
|
||||
# run tests
|
||||
docker buildx bake test
|
||||
```
|
||||
|
||||
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
|
||||
|
||||
- Make sure the `README.md` and any other relevant **documentation are kept up-to-date**.
|
||||
|
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -381,10 +381,8 @@ jobs:
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
# TODO: Remove image=moby/buildkit:buildx-stable-1 when moby/buildkit#1727 fixed
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
-
|
||||
name: Build and push (1)
|
||||
id: docker_build
|
||||
@ -481,10 +479,8 @@ jobs:
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
# TODO: Remove image=moby/buildkit:buildx-stable-1 when moby/buildkit#1727 fixed
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
-
|
||||
name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
@ -551,10 +547,8 @@ jobs:
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
# TODO: Remove image=moby/buildkit:buildx-stable-1 when moby/buildkit#1727 fixed
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
-
|
||||
name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
|
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@ -9,6 +9,19 @@ on:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
test-containerized:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.3
|
||||
-
|
||||
name: Validate
|
||||
run: docker buildx bake validate
|
||||
-
|
||||
name: Test
|
||||
run: docker buildx bake test
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
52
Dockerfile
Normal file
52
Dockerfile
Normal file
@ -0,0 +1,52 @@
|
||||
#syntax=docker/dockerfile:1.1-experimental
|
||||
|
||||
FROM node:12 AS deps
|
||||
WORKDIR /src
|
||||
COPY package.json yarn.lock ./
|
||||
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \
|
||||
yarn install
|
||||
|
||||
FROM scratch AS update-yarn
|
||||
COPY --from=deps /src/yarn.lock /
|
||||
|
||||
FROM deps AS validate-yarn
|
||||
COPY .git .git
|
||||
RUN status=$(git status --porcelain -- yarn.lock); if [ -n "$status" ]; then echo $status; exit 1; fi
|
||||
|
||||
FROM deps AS base
|
||||
COPY . .
|
||||
|
||||
FROM base AS build
|
||||
RUN yarn build
|
||||
|
||||
FROM deps AS test
|
||||
COPY --from=docker /usr/local/bin/docker /usr/bin/
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG BUILDX_VERSION=v0.4.2
|
||||
ENV RUNNER_TEMP=/tmp/github_runner
|
||||
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
|
||||
RUN mkdir -p /usr/local/lib/docker/cli-plugins && \
|
||||
curl -fsSL https://github.com/docker/buildx/releases/download/$BUILDX_VERSION/buildx-$BUILDX_VERSION.$TARGETOS-$TARGETARCH > /usr/local/lib/docker/cli-plugins/docker-buildx && \
|
||||
chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx && \
|
||||
docker buildx version
|
||||
COPY . .
|
||||
RUN yarn run test
|
||||
|
||||
FROM base AS run-format
|
||||
RUN yarn run format
|
||||
|
||||
FROM scratch AS format
|
||||
COPY --from=run-format /src/src/*.ts /src/
|
||||
|
||||
FROM base AS validate-format
|
||||
RUN yarn run format-check
|
||||
|
||||
FROM scratch AS dist
|
||||
COPY --from=build /src/dist/ /dist/
|
||||
|
||||
FROM build AS validate-build
|
||||
RUN status=$(git status --porcelain -- dist); if [ -n "$status" ]; then echo $status; exit 1; fi
|
||||
|
||||
FROM base AS dev
|
||||
ENTRYPOINT ["bash"]
|
@ -1,6 +1,114 @@
|
||||
# Troubleshooting
|
||||
|
||||
## Errors on pushing to registry
|
||||
* [`auto-push is currently not implemented for docker driver`](#auto-push-is-currently-not-implemented-for-docker-driver)
|
||||
* [Cannot push to a registry](#cannot-push-to-a-registry)
|
||||
|
||||
## `auto-push is currently not implemented for docker driver`
|
||||
|
||||
If you're using the default builder (which uses the docker driver) without using our `setup-buildx-action`, you may
|
||||
encounter this error message if you try to push your image:
|
||||
|
||||
```
|
||||
Run docker/build-push-action@v2
|
||||
📣 Buildx version: 0.4.2
|
||||
🏃 Starting build...
|
||||
/usr/bin/docker buildx build --tag localhost:5000/name/app:latest --iidfile /tmp/docker-build-push-eYl8PB/iidfile --file ./test/Dockerfile --push ./test
|
||||
auto-push is currently not implemented for docker driver
|
||||
Error: buildx call failed with: auto-push is currently not implemented for docker driver
|
||||
```
|
||||
|
||||
While waiting for an implementation to be done on buildx/buildkit, you have the following possibilities
|
||||
to solve this atm:
|
||||
|
||||
### With `docker-container` driver and `setup-buildx`
|
||||
|
||||
> Recommended solution
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Login
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ env.USER }}
|
||||
password: ${{ secrets.PASSWORD }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
tags: ${{ env.REGISTRY }}/myapp:latest
|
||||
push: true
|
||||
```
|
||||
|
||||
### With `docker` driver
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Login
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ env.USER }}
|
||||
password: ${{ secrets.PASSWORD }}
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
tags: ${{ env.REGISTRY }}/myapp:latest
|
||||
load: true
|
||||
-
|
||||
name: Push
|
||||
run: docker push ${{ env.REGISTRY }}/myapp:latest
|
||||
```
|
||||
|
||||
### With `docker` driver and `setup-buildx`
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
driver: docker
|
||||
-
|
||||
name: Login
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ env.USER }}
|
||||
password: ${{ secrets.PASSWORD }}
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
tags: ${{ env.REGISTRY }}/myapp:latest
|
||||
load: true
|
||||
-
|
||||
name: Push
|
||||
run: docker push ${{ env.REGISTRY }}/myapp:latest
|
||||
```
|
||||
|
||||
## Cannot push to a registry
|
||||
|
||||
While pushing to a registry, you may encounter these kinds of issues:
|
||||
|
||||
@ -38,7 +146,7 @@ jobs:
|
||||
containerd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
|
@ -2,9 +2,10 @@ import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as buildx from '../src/buildx';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as docker from '../src/docker';
|
||||
import * as context from '../src/context';
|
||||
|
||||
const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||
const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
|
||||
|
||||
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||
@ -16,7 +17,7 @@ jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||
});
|
||||
|
||||
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||
return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||
return tmpNameSync;
|
||||
});
|
||||
|
||||
describe('getImageID', () => {
|
||||
@ -91,11 +92,18 @@ describe('isLocalOrTarExporter', () => {
|
||||
});
|
||||
|
||||
describe('getVersion', () => {
|
||||
it('valid', async () => {
|
||||
const version = await buildx.getVersion();
|
||||
console.log(`version: ${version}`);
|
||||
expect(semver.valid(version)).not.toBeNull();
|
||||
}, 100000);
|
||||
async function isDaemonRunning() {
|
||||
return await docker.isDaemonRunning();
|
||||
}
|
||||
(isDaemonRunning() ? it : it.skip)(
|
||||
'valid',
|
||||
async () => {
|
||||
const version = await buildx.getVersion();
|
||||
console.log(`version: ${version}`);
|
||||
expect(semver.valid(version)).not.toBeNull();
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
|
||||
describe('parseVersion', () => {
|
||||
@ -107,3 +115,18 @@ describe('parseVersion', () => {
|
||||
expect(await buildx.parseVersion(stdout)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSecret', () => {
|
||||
test.each([
|
||||
['A_SECRET', 'abcdef0123456789'],
|
||||
['GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789'],
|
||||
['MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==']
|
||||
])('given %p key and %p secret', async (key, secret) => {
|
||||
const secretArgs = await buildx.getSecret(`${key}=${secret}`);
|
||||
console.log(`secretArgs: ${secretArgs}`);
|
||||
expect(secretArgs).toEqual(`id=${key},src=${tmpNameSync}`);
|
||||
const secretContent = await fs.readFileSync(tmpNameSync, 'utf-8');
|
||||
console.log(`secretValue: ${secretContent}`);
|
||||
expect(secretContent).toEqual(secret);
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as buildx from '../src/buildx';
|
||||
import * as context from '../src/context';
|
||||
|
||||
jest.spyOn(context, 'defaultContext').mockImplementation((): string => {
|
||||
@ -107,7 +106,7 @@ describe('getArgs', () => {
|
||||
'0.4.2',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno0123456789'],
|
||||
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'],
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
@ -139,7 +138,7 @@ describe('getArgs', () => {
|
||||
['context', 'https://github.com/docker/build-push-action.git#heads/master'],
|
||||
['tag', 'localhost:5000/name/app:latest'],
|
||||
['platforms', 'linux/amd64,linux/arm64'],
|
||||
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno0123456789'],
|
||||
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'],
|
||||
['file', './test/Dockerfile'],
|
||||
['builder', 'builder-git-context-2'],
|
||||
['push', 'true']
|
||||
|
3313
dist/index.js
generated
vendored
3313
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
42
docker-bake.hcl
Normal file
42
docker-bake.hcl
Normal file
@ -0,0 +1,42 @@
|
||||
group "default" {
|
||||
targets = ["build"]
|
||||
}
|
||||
|
||||
group "pre-checkin" {
|
||||
targets = ["update-yarn", "format", "build"]
|
||||
}
|
||||
|
||||
group "validate" {
|
||||
targets = ["validate-format", "validate-build", "validate-yarn"]
|
||||
}
|
||||
|
||||
target "update-yarn" {
|
||||
target = "update-yarn"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "build" {
|
||||
target = "dist"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "test" {
|
||||
target = "test"
|
||||
}
|
||||
|
||||
target "format" {
|
||||
target = "format"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "validate-format" {
|
||||
target = "validate-format"
|
||||
}
|
||||
|
||||
target "validate-build" {
|
||||
target = "validate-build"
|
||||
}
|
||||
|
||||
target "validate-yarn" {
|
||||
target = "validate-yarn"
|
||||
}
|
@ -18,7 +18,9 @@ export async function getImageID(): Promise<string | undefined> {
|
||||
}
|
||||
|
||||
export async function getSecret(kvp: string): Promise<string> {
|
||||
const [key, value] = kvp.split('=');
|
||||
const delimiterIndex = kvp.indexOf('=');
|
||||
const key = kvp.substring(0, delimiterIndex);
|
||||
const value = kvp.substring(delimiterIndex + 1);
|
||||
const secretFile = context.tmpNameSync({
|
||||
tmpdir: context.tmpDir()
|
||||
});
|
||||
|
7
src/docker.ts
Normal file
7
src/docker.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import * as exec from './exec';
|
||||
|
||||
export async function isDaemonRunning(): Promise<boolean> {
|
||||
return await exec.exec(`docker`, ['version', '--format', '{{.Server.Os}}'], true).then(res => {
|
||||
return !res.stdout.includes(' ') && res.success;
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user