Merge pull request #136 from crazy-max/auto-git-token

Expose Git secret token if default context used
This commit is contained in:
CrazyMax 2020-09-23 11:23:48 +02:00 committed by GitHub
commit a2578e544b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 206 additions and 152 deletions

@ -11,11 +11,53 @@ on:
jobs: jobs:
git-context: git-context:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: services:
fail-fast: false registry:
matrix: image: registry:2
buildx-version: ports:
- latest - 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
with:
platforms: all
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
version: latest
driver-opts: network=host
-
name: Build and push
id: docker_build
uses: ./
with:
file: ./test/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1
git-context-secret:
runs-on: ubuntu-latest
services: services:
registry: registry:
image: registry:2 image: registry:2

259
README.md

@ -45,10 +45,7 @@ build-secrets, remote cache, etc. and different builder deployment/namespacing o
The default behavior of this action is to use the [Git context invoked by your workflow](https://github.com/docker/build-push-action/blob/master/src/context.ts#L35). The default behavior of this action is to use the [Git context invoked by your workflow](https://github.com/docker/build-push-action/blob/master/src/context.ts#L35).
<details> ```yaml
<summary><b>Show workflow</b></summary>
```yaml
name: ci name: ci
on: on:
@ -81,11 +78,11 @@ jobs:
- -
name: Image digest name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }} run: echo ${{ steps.docker_build.outputs.digest }}
``` ```
</details>
If you use this action in a private repository, you have to pass the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token) Building from current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token)
as a secret named `GIT_AUTH_TOKEN` to be able to authenticate against it with buildx: as provided by `secrets` so it does not need to be passed. But if you want to authenticate against another private
repository, you have to use a secret named `GIT_AUTH_TOKEN` to be able to authenticate against it with buildx:
```yaml ```yaml
- -
@ -96,7 +93,7 @@ as a secret named `GIT_AUTH_TOKEN` to be able to authenticate against it with bu
push: true push: true
tags: user/app:latest tags: user/app:latest
secrets: | secrets: |
GIT_AUTH_TOKEN=${{ github.token }} GIT_AUTH_TOKEN=${{ secrets.MYTOKEN }}
``` ```
> :warning: Subdir for Git context is [not yet supported](https://github.com/docker/build-push-action/issues/120). > :warning: Subdir for Git context is [not yet supported](https://github.com/docker/build-push-action/issues/120).
@ -106,140 +103,128 @@ as a secret named `GIT_AUTH_TOKEN` to be able to authenticate against it with bu
You can also use the `PATH` context alongside the [`actions/checkout`](https://github.com/actions/checkout/) action. You can also use the `PATH` context alongside the [`actions/checkout`](https://github.com/actions/checkout/) action.
<details> ```yaml
<summary><b>Show workflow</b></summary> name: ci
```yaml
name: ci
on: on:
push: push:
branches: master branches: master
jobs: jobs:
path-context: path-context:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- -
name: Set up QEMU name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1
- -
name: Set up Docker Buildx name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- -
name: Login to DockerHub name: Login to DockerHub
uses: docker/login-action@v1 uses: docker/login-action@v1
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- -
name: Build and push name: Build and push
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/386 platforms: linux/amd64,linux/arm64,linux/386
push: true push: true
tags: user/app:latest tags: user/app:latest
``` ```
</details>
### Isolated builders ### Isolated builders
<details> ```yaml
<summary><b>Show workflow</b></summary> name: ci
```yaml
name: ci
on: on:
push: push:
branches: master branches: master
jobs: jobs:
multi-builders: multi-builders:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- -
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
id: builder1 id: builder1
- -
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
id: builder2 id: builder2
- -
name: Builder 1 name name: Builder 1 name
run: echo ${{ steps.builder1.outputs.name }} run: echo ${{ steps.builder1.outputs.name }}
- -
name: Builder 2 name name: Builder 2 name
run: echo ${{ steps.builder2.outputs.name }} run: echo ${{ steps.builder2.outputs.name }}
- -
name: Build against builder1 name: Build against builder1
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
builder: ${{ steps.builder1.outputs.name }} builder: ${{ steps.builder1.outputs.name }}
target: mytarget1 target: mytarget1
- -
name: Build against builder2 name: Build against builder2
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
builder: ${{ steps.builder2.outputs.name }} builder: ${{ steps.builder2.outputs.name }}
target: mytarget2 target: mytarget2
``` ```
</details>
### Multi-platform image ### Multi-platform image
<details> ```yaml
<summary><b>Show workflow</b></summary> name: ci
```yaml
name: ci
on: on:
push: push:
branches: master branches: master
jobs: jobs:
multi: multi:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- -
name: Set up QEMU name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1
- -
name: Set up Docker Buildx name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- -
name: Login to DockerHub name: Login to DockerHub
uses: docker/login-action@v1 uses: docker/login-action@v1
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- -
name: Build and push name: Build and push
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: true push: true
tags: | tags: |
user/app:latest user/app:latest
user/app:1.0.0 user/app:1.0.0
``` ```
</details>
## Advanced usage ## Advanced usage
### Local registry ### Local registry
For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) to push images into. For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) to push images into:
<details> <details>
<summary><b>Show workflow</b></summary> <summary><b>Show workflow</b></summary>
@ -284,7 +269,7 @@ For testing purposes you may need to create a [local registry](https://hub.docke
### Leverage GitHub cache ### Leverage GitHub cache
You can leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows) You can leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)
using [actions/cache](https://github.com/actions/cache) with this action. using [actions/cache](https://github.com/actions/cache) with this action:
<details> <details>
<summary><b>Show workflow</b></summary> <summary><b>Show workflow</b></summary>
@ -338,15 +323,6 @@ The following workflow with the `Prepare` step will generate some [outputs](http
to handle tags and labels based on GitHub actions events. This is just an example to show many cases that you to handle tags and labels based on GitHub actions events. This is just an example to show many cases that you
might want to use: might want to use:
| Event | Ref | Commit SHA | Docker Tag | Pushed |
|-----------------|-------------------------------|------------|------------------------------------|--------|
| `schedule` | | | `nightly` | Yes |
| `pull_request` | `refs/pull/2/merge` | `a123b57` | `pr-2` | No |
| `push` | `refs/heads/<default_branch>` | `676cae2` | `sha-676cae2`, `edge` | Yes |
| `push` | `refs/heads/dev` | `cf20257` | `sha-cf20257`, `dev` | Yes |
| `push` | `refs/heads/my/branch` | `a5df687` | `sha-a5df687`, `my-branch` | Yes |
| `push tag` | `refs/tags/v1.2.3` | | `v1.2.3`, `v1.2`, `v1`, `latest` | Yes |
<details> <details>
<summary><b>Show workflow</b></summary> <summary><b>Show workflow</b></summary>
@ -434,11 +410,20 @@ might want to use:
``` ```
</details> </details>
| Event | Ref | Commit SHA | Docker Tag | Pushed |
|-----------------|-------------------------------|------------|------------------------------------|--------|
| `schedule` | | | `nightly` | Yes |
| `pull_request` | `refs/pull/2/merge` | `a123b57` | `pr-2` | No |
| `push` | `refs/heads/<default_branch>` | `676cae2` | `sha-676cae2`, `edge` | Yes |
| `push` | `refs/heads/dev` | `cf20257` | `sha-cf20257`, `dev` | Yes |
| `push` | `refs/heads/my/branch` | `a5df687` | `sha-a5df687`, `my-branch` | Yes |
| `push tag` | `refs/tags/v1.2.3` | | `v1.2.3`, `v1.2`, `v1`, `latest` | Yes |
### Update DockerHub repo description ### Update DockerHub repo description
You can update the [Docker Hub repository description](https://docs.docker.com/docker-hub/repos/) using You can update the [Docker Hub repository description](https://docs.docker.com/docker-hub/repos/) using
a third-party action called [Docker Hub Description](https://github.com/peter-evans/dockerhub-description) a third-party action called [Docker Hub Description](https://github.com/peter-evans/dockerhub-description)
with this action. with this action:
<details> <details>
<summary><b>Show workflow</b></summary> <summary><b>Show workflow</b></summary>

@ -64,6 +64,10 @@ inputs:
secrets: secrets:
description: "List of secrets to expose to the build (eg. key=value, GIT_AUTH_TOKEN=mytoken)" description: "List of secrets to expose to the build (eg. key=value, GIT_AUTH_TOKEN=mytoken)"
required: false required: false
github-token:
description: "GitHub Token used to authenticate against a repository for Git context"
default: ${{ github.token }}
required: false
outputs: outputs:
digest: digest:

25
dist/index.js generated vendored

@ -7955,6 +7955,12 @@ function convertBody(buffer, headers) {
// html4 // html4
if (!res && str) { if (!res && str) {
res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str); res = /<meta[\s]+?http-equiv=(['"])content-type\1[\s]+?content=(['"])(.+?)\2/i.exec(str);
if (!res) {
res = /<meta[\s]+?content=(['"])(.+?)\1[\s]+?http-equiv=(['"])content-type\3/i.exec(str);
if (res) {
res.pop(); // drop last quote
}
}
if (res) { if (res) {
res = /charset=(.*)/i.exec(res.pop()); res = /charset=(.*)/i.exec(res.pop());
@ -8962,7 +8968,7 @@ function fetch(url, opts) {
// HTTP fetch step 5.5 // HTTP fetch step 5.5
switch (request.redirect) { switch (request.redirect) {
case 'error': case 'error':
reject(new FetchError(`redirect mode is set to error: ${request.url}`, 'no-redirect')); reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect'));
finalize(); finalize();
return; return;
case 'manual': case 'manual':
@ -9001,7 +9007,8 @@ function fetch(url, opts) {
method: request.method, method: request.method,
body: request.body, body: request.body,
signal: request.signal, signal: request.signal,
timeout: request.timeout timeout: request.timeout,
size: request.size
}; };
// HTTP-redirect fetch step 9 // HTTP-redirect fetch step 9
@ -13640,11 +13647,11 @@ const buildx = __importStar(__webpack_require__(295));
const core = __importStar(__webpack_require__(186)); const core = __importStar(__webpack_require__(186));
const github = __importStar(__webpack_require__(438)); const github = __importStar(__webpack_require__(438));
exports.tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-')); exports.tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-'));
const defaultContext = `https://github.com/${github.context.repo.owner}/${github.context.repo.repo}#${github.context.ref}`;
function getInputs() { function getInputs() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
return { return {
context: core.getInput('context') || context: core.getInput('context') || defaultContext,
`https://github.com/${github.context.repo.owner}/${github.context.repo.repo}#${github.context.ref}`,
file: core.getInput('file') || 'Dockerfile', file: core.getInput('file') || 'Dockerfile',
buildArgs: yield getInputList('build-args'), buildArgs: yield getInputList('build-args'),
labels: yield getInputList('labels'), labels: yield getInputList('labels'),
@ -13660,7 +13667,8 @@ function getInputs() {
outputs: yield getInputList('outputs', true), outputs: yield getInputList('outputs', true),
cacheFrom: yield getInputList('cache-from', true), cacheFrom: yield getInputList('cache-from', true),
cacheTo: yield getInputList('cache-to', true), cacheTo: yield getInputList('cache-to', true),
secrets: yield getInputList('secrets', true) secrets: yield getInputList('secrets', true),
githubToken: core.getInput('github-token')
}; };
}); });
} }
@ -13708,9 +13716,16 @@ function getBuildArgs(inputs, buildxVersion) {
yield exports.asyncForEach(inputs.cacheTo, (cacheTo) => __awaiter(this, void 0, void 0, function* () { yield exports.asyncForEach(inputs.cacheTo, (cacheTo) => __awaiter(this, void 0, void 0, function* () {
args.push('--cache-to', cacheTo); args.push('--cache-to', cacheTo);
})); }));
let hasGitAuthToken = false;
yield exports.asyncForEach(inputs.secrets, (secret) => __awaiter(this, void 0, void 0, function* () { yield exports.asyncForEach(inputs.secrets, (secret) => __awaiter(this, void 0, void 0, function* () {
if (secret.startsWith('GIT_AUTH_TOKEN=')) {
hasGitAuthToken = true;
}
args.push('--secret', yield buildx.getSecret(secret)); args.push('--secret', yield buildx.getSecret(secret));
})); }));
if (inputs.githubToken && !hasGitAuthToken && inputs.context == defaultContext) {
args.push('--secret', yield buildx.getSecret(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
}
if (inputs.file) { if (inputs.file) {
args.push('--file', inputs.file); args.push('--file', inputs.file);
} }

@ -6,7 +6,8 @@ import * as buildx from './buildx';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as github from '@actions/github'; import * as github from '@actions/github';
export const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-')); export const tmpDir: string = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-'));
const defaultContext: string = `https://github.com/${github.context.repo.owner}/${github.context.repo.repo}#${github.context.ref}`;
export interface Inputs { export interface Inputs {
context: string; context: string;
@ -26,13 +27,12 @@ export interface Inputs {
cacheFrom: string[]; cacheFrom: string[];
cacheTo: string[]; cacheTo: string[];
secrets: string[]; secrets: string[];
githubToken: string;
} }
export async function getInputs(): Promise<Inputs> { export async function getInputs(): Promise<Inputs> {
return { return {
context: context: core.getInput('context') || defaultContext,
core.getInput('context') ||
`https://github.com/${github.context.repo.owner}/${github.context.repo.repo}#${github.context.ref}`,
file: core.getInput('file') || 'Dockerfile', file: core.getInput('file') || 'Dockerfile',
buildArgs: await getInputList('build-args'), buildArgs: await getInputList('build-args'),
labels: await getInputList('labels'), labels: await getInputList('labels'),
@ -48,7 +48,8 @@ export async function getInputs(): Promise<Inputs> {
outputs: await getInputList('outputs', true), outputs: await getInputList('outputs', true),
cacheFrom: await getInputList('cache-from', true), cacheFrom: await getInputList('cache-from', true),
cacheTo: await getInputList('cache-to', true), cacheTo: await getInputList('cache-to', true),
secrets: await getInputList('secrets', true) secrets: await getInputList('secrets', true),
githubToken: core.getInput('github-token')
}; };
} }
@ -92,9 +93,16 @@ async function getBuildArgs(inputs: Inputs, buildxVersion: string): Promise<Arra
await asyncForEach(inputs.cacheTo, async cacheTo => { await asyncForEach(inputs.cacheTo, async cacheTo => {
args.push('--cache-to', cacheTo); args.push('--cache-to', cacheTo);
}); });
let hasGitAuthToken: boolean = false;
await asyncForEach(inputs.secrets, async secret => { await asyncForEach(inputs.secrets, async secret => {
if (secret.startsWith('GIT_AUTH_TOKEN=')) {
hasGitAuthToken = true;
}
args.push('--secret', await buildx.getSecret(secret)); args.push('--secret', await buildx.getSecret(secret));
}); });
if (inputs.githubToken && !hasGitAuthToken && inputs.context == defaultContext) {
args.push('--secret', await buildx.getSecret(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
}
if (inputs.file) { if (inputs.file) {
args.push('--file', inputs.file); args.push('--file', inputs.file);
} }