Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate bake file for docker/bake-action #977

Merged
merged 9 commits into from
Dec 8, 2024
Merged
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
20 changes: 14 additions & 6 deletions .github/workflows/ts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ jobs:
- run: pnpm test
- run: pnpm build

# e2e test
- uses: ./
id: cache-params
# E2E test
- name: Run int128/docker-build-cache-config-action
uses: ./
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
- uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1
Expand All @@ -48,14 +49,21 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
- uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0
id: build
with:
context: tests/fixture
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache-params.outputs.cache-from }}
cache-to: ${{ steps.cache-params.outputs.cache-to }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
- uses: docker/bake-action@3fc70e1131fee40a422dd8dd0ff22014ae20a1f3 # v5.11.0
with:
workdir: tests/fixture
push: ${{ github.event_name == 'push' }}
files: |
./docker-bake.hcl
${{ steps.metadata.outputs.bake-file }}
${{ steps.cache.outputs.bake-file }}

generate:
runs-on: ubuntu-latest
Expand Down
61 changes: 50 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ This action generates the cache parameters by this strategy.

## Examples

Here is an example to store a cache into GHCR (GitHub Container Registry).
### Build with docker/build-push-action

Here is an example to build a container image with [docker/build-push-action](https://github.com/docker/build-push-action).

```yaml
- uses: docker/metadata-action@v3
Expand Down Expand Up @@ -110,20 +112,56 @@ ghcr.io/${{ github.repository }}/cache:main

See [README_EXAMPLES.md](README_EXAMPLES.md) for more examples.

### Build with docker/bake-action

Here is an example to build a container image with [docker/bake-action](https://github.com/docker/bake-action).

```yaml
- uses: docker/metadata-action@v3
id: metadata
with:
images: ghcr.io/${{ github.repository }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
- uses: docker/bake-action@v5
id: build
with:
push: true
files: |
./docker-bake.hcl
${{ steps.metadata.outputs.bake-file }}
${{ steps.cache.outputs.bake-file }}
```

```hcl
# docker-bake.hcl
target "docker-metadata-action" {}

target "docker-build-cache-config-action" {}

target "default" {
inherits = ["docker-metadata-action", "docker-build-cache-config-action"]
context = "."
}
```

## Specification

### Inputs

| Name | Default | Description |
| -------------------- | ---------- | ---------------------------------------------------------------------------------------------- |
| `image` | (required) | Image repository to import/export cache |
| `cache-type` | `registry` | Type of cache backend (for source and destination). Can be registry, local, inline, gha and s3 |
| `flavor` | - | Flavor (multiline string) |
| `extra-cache-from` | - | Extra flag to `cache-from` |
| `extra-cache-to` | - | Extra flag to `cache-to` |
| `pull-request-cache` | - | Import and export a pull request cache |
| `cache-key` | - | Custom cache key |
| `cache-key-fallback` | - | Custom cache key to fallback |
| Name | Default | Description |
| -------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------- |
| `image` | (required) | Image repository to import/export cache |
| `cache-type` | `registry` | Type of cache backend (for source and destination). Can be registry, local, inline, gha and s3 |
| `flavor` | - | Flavor (multiline string) |
| `extra-cache-from` | - | Extra flag to `cache-from` |
| `extra-cache-to` | - | Extra flag to `cache-to` |
| `pull-request-cache` | - | Import and export a pull request cache |
| `cache-key` | - | Custom cache key |
| `cache-key-fallback` | - | Custom cache key to fallback |
| `bake-target` | `docker-build-cache-config-action` | Bake target name |

`flavor` is mostly compatible with [docker/metadata-action](https://github.com/docker/metadata-action#flavor-input)
except this action supports only `prefix` and `suffix`.
Expand All @@ -139,6 +177,7 @@ The specification may change in the future.
| ------------ | -------------------------------------- |
| `cache-from` | Parameter for docker/build-push-action |
| `cache-to` | Parameter for docker/build-push-action |
| `bake-file` | Bake definition file |

### Events

Expand Down
6 changes: 6 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ inputs:
cache-key-fallback:
description: Custom cache key to fallback (experimental)
required: false
bake-target:
description: Bake target name
required: false
default: docker-build-cache-config-action
token:
description: GitHub token
required: false
Expand All @@ -38,6 +42,8 @@ outputs:
description: cache-from parameter for docker/build-push-action
cache-to:
description: cache-to parameter for docker/build-push-action
bake-file:
description: Bake definition file

runs:
using: 'node20'
Expand Down
20 changes: 20 additions & 0 deletions src/bake.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { DockerFlags } from './docker.js'

type Bake = {
target: {
[target: string]: {
// https://docs.docker.com/build/bake/reference/#target
'cache-from': string[]
'cache-to': string[]
}
}
}

export const generateBake = (target: string, flags: DockerFlags): Bake => ({
target: {
[target]: {
'cache-from': flags.cacheFrom,
'cache-to': flags.cacheTo,
},
},
})
12 changes: 6 additions & 6 deletions src/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ type Inputs = {
extraCacheTo: string
}

type Outputs = {
cacheFrom: string
cacheTo: string
export type DockerFlags = {
cacheFrom: string[]
cacheTo: string[]
}

export const generateDockerFlags = (inputs: Inputs): Outputs => {
export const generateDockerFlags = (inputs: Inputs): DockerFlags => {
const cacheType = `type=${inputs.cacheType}`

const cacheFrom = inputs.cacheFromImageTag.map((tag) => {
Expand All @@ -34,7 +34,7 @@ export const generateDockerFlags = (inputs: Inputs): Outputs => {
})

return {
cacheFrom: cacheFrom.join('\n'),
cacheTo: cacheTo.join('\n'),
cacheFrom,
cacheTo,
}
}
3 changes: 3 additions & 0 deletions src/github.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import * as github from '@actions/github'
import * as os from 'os'

export type Octokit = ReturnType<typeof github.getOctokit>

// For testability, use a subset of github.context in this module.
export type Context = Pick<typeof github.context, 'eventName' | 'ref' | 'payload' | 'repo' | 'issue'>

export const getRunnerTemp = (): string => process.env.RUNNER_TEMP || os.tmpdir()
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ const main = async (): Promise<void> => {
cacheKeyFallback: core.getMultilineInput('cache-key-fallback'),
extraCacheFrom: core.getInput('extra-cache-from'),
extraCacheTo: core.getInput('extra-cache-to'),
bakeTarget: core.getInput('bake-target', { required: true }),
context: github.context,
octokit: github.getOctokit(core.getInput('token', { required: true })),
})
core.info(`Setting outputs: ${JSON.stringify(outputs, undefined, 2)}`)
core.setOutput('cache-from', outputs.cacheFrom)
core.setOutput('cache-to', outputs.cacheTo)
core.setOutput('bake-file', outputs.bakeFile)
}

main().catch((e: Error) => {
Expand Down
23 changes: 21 additions & 2 deletions src/run.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import * as core from '@actions/core'
import { Context, Octokit } from './github.js'
import * as fs from 'fs/promises'
import * as path from 'path'
import { Context, getRunnerTemp, Octokit } from './github.js'
import { inferImageTags } from './infer.js'
import { CacheType, generateDockerFlags } from './docker.js'
import { generateBake } from './bake.js'

type Inputs = {
image: string
Expand All @@ -12,13 +15,15 @@ type Inputs = {
cacheKeyFallback: string[]
extraCacheFrom: string
extraCacheTo: string
bakeTarget: string
context: Context
octokit: Octokit
}

type Outputs = {
cacheFrom: string
cacheTo: string
bakeFile: string
}

export const run = async (inputs: Inputs): Promise<Outputs> => {
Expand All @@ -31,11 +36,25 @@ export const run = async (inputs: Inputs): Promise<Outputs> => {
})
core.info(`Inferred cache-from: ${tags.from.join(', ')}`)
core.info(`Inferred cache-to: ${tags.to.join(', ')}`)
return generateDockerFlags({
const dockerFlags = generateDockerFlags({
cacheType: inputs.cacheType,
cacheFromImageTag: tags.from,
cacheToImageTag: tags.to,
extraCacheFrom: inputs.extraCacheFrom,
extraCacheTo: inputs.extraCacheTo,
})

const bake = generateBake(inputs.bakeTarget, dockerFlags)
core.startGroup('Bake file definition')
core.info(JSON.stringify(bake, undefined, 2))
core.endGroup()

const tempDir = await fs.mkdtemp(path.join(getRunnerTemp(), 'docker-build-cache-config-action-'))
const bakeFile = `${tempDir}/docker-build-cache-config-action-bake.json`
await fs.writeFile(bakeFile, JSON.stringify(bake))
return {
cacheFrom: dockerFlags.cacheFrom.join('\n'),
cacheTo: dockerFlags.cacheTo.join('\n'),
bakeFile,
}
}
29 changes: 14 additions & 15 deletions tests/docker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ test('both from and to', () => {
extraCacheTo: '',
})
expect(outputs).toStrictEqual({
cacheFrom: 'type=registry,ref=ghcr.io/int128/sandbox/cache:main',
cacheTo: 'type=registry,ref=ghcr.io/int128/sandbox/cache:main,mode=max',
cacheFrom: ['type=registry,ref=ghcr.io/int128/sandbox/cache:main'],
cacheTo: ['type=registry,ref=ghcr.io/int128/sandbox/cache:main,mode=max'],
})
})

Expand All @@ -23,8 +23,8 @@ test('only from', () => {
extraCacheTo: '',
})
expect(outputs).toStrictEqual({
cacheFrom: 'type=registry,ref=ghcr.io/int128/sandbox/cache:main',
cacheTo: '',
cacheFrom: ['type=registry,ref=ghcr.io/int128/sandbox/cache:main'],
cacheTo: [],
})
})

Expand All @@ -37,8 +37,8 @@ test('both from and to with extra args', () => {
extraCacheTo: 'image-manifest=true',
})
expect(outputs).toStrictEqual({
cacheFrom: 'type=registry,ref=ghcr.io/int128/sandbox/cache:main,foo=bar',
cacheTo: 'type=registry,ref=ghcr.io/int128/sandbox/cache:main,mode=max,image-manifest=true',
cacheFrom: ['type=registry,ref=ghcr.io/int128/sandbox/cache:main,foo=bar'],
cacheTo: ['type=registry,ref=ghcr.io/int128/sandbox/cache:main,mode=max,image-manifest=true'],
})
})

Expand All @@ -51,8 +51,8 @@ test('only from with extra args', () => {
extraCacheTo: 'image-manifest=true',
})
expect(outputs).toStrictEqual({
cacheFrom: 'type=registry,ref=ghcr.io/int128/sandbox/cache:main,foo=bar',
cacheTo: '',
cacheFrom: ['type=registry,ref=ghcr.io/int128/sandbox/cache:main,foo=bar'],
cacheTo: [],
})
})

Expand All @@ -65,11 +65,11 @@ test('both multiple from and to', () => {
extraCacheTo: '',
})
expect(outputs).toStrictEqual({
cacheFrom:
'type=registry,ref=ghcr.io/int128/sandbox/cache:pr-1' +
'\n' +
cacheFrom: [
'type=registry,ref=ghcr.io/int128/sandbox/cache:pr-1',
'type=registry,ref=ghcr.io/int128/sandbox/cache:main',
cacheTo: 'type=registry,ref=ghcr.io/int128/sandbox/cache:pr-1,mode=max',
],
cacheTo: ['type=registry,ref=ghcr.io/int128/sandbox/cache:pr-1,mode=max'],
})
})

Expand All @@ -82,8 +82,7 @@ test('cache type', () => {
extraCacheTo: '',
})
expect(outputs).toStrictEqual({
cacheFrom:
'type=gha,ref=ghcr.io/int128/sandbox/cache:pr-1' + '\n' + 'type=gha,ref=ghcr.io/int128/sandbox/cache:main',
cacheTo: 'type=gha,ref=ghcr.io/int128/sandbox/cache:pr-1,mode=max',
cacheFrom: ['type=gha,ref=ghcr.io/int128/sandbox/cache:pr-1', 'type=gha,ref=ghcr.io/int128/sandbox/cache:main'],
cacheTo: ['type=gha,ref=ghcr.io/int128/sandbox/cache:pr-1,mode=max'],
})
})
8 changes: 8 additions & 0 deletions tests/fixture/docker-bake.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
target "docker-metadata-action" {}

target "docker-build-cache-config-action" {}

target "default" {
inherits = ["docker-metadata-action", "docker-build-cache-config-action"]
context = "."
}
Loading
Loading