diff --git a/README.md b/README.md index 2e52e0f1e..c1194af19 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,17 @@ ___ * [Customizing](#customizing) * [inputs](#inputs) * [outputs](#outputs) +* [`flavor` input](#flavor-input) +* [`tags` input](#tags-input) + * [`type=schedule`](#typeschedule) + * [`type=semver`](#typesemver) + * [`type=match`](#typematch) + * [`type=edge`](#typeedge) + * [`type=ref`](#typeref) + * [`type=raw`](#typeraw) + * [`type=sha`](#typesha) * [Notes](#notes) * [Latest tag](#latest-tag) - * [Handle semver tag](#handle-semver-tag) - * [`tag-match` examples](#tag-match-examples) - * [Schedule tag](#schedule-tag) * [Overwrite labels](#overwrite-labels) * [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot) * [Contributing](#contributing) @@ -37,24 +43,20 @@ ___ ### Basic -| Event | Ref | Commit SHA | Docker Tags | -|-----------------|-------------------------------|------------|-------------------------------------| -| `pull_request` | `refs/pull/2/merge` | `a123b57` | `pr-2` | -| `push` | `refs/heads/master` | `cf20257` | `master` | -| `push` | `refs/heads/my/branch` | `a5df687` | `my-branch` | -| `push tag` | `refs/tags/v1.2.3` | `ad132f5` | `v1.2.3`, `latest` | -| `push tag` | `refs/tags/v2.0.8-beta.67` | `fc89efd` | `v2.0.8-beta.67`, `latest` | - ```yaml name: ci on: push: branches: - - '**' + - 'master' + - 'release/v*' tags: - 'v*' pull_request: + branches: + - 'master' + - 'release/v*' jobs: docker: @@ -65,16 +67,10 @@ jobs: uses: actions/checkout@v2 - name: Docker meta - id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 + id: meta + uses: crazy-max/ghaction-docker-meta@v2 with: images: name/app - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - name: Login to DockerHub if: github.event_name != 'pull_request' @@ -87,22 +83,20 @@ jobs: uses: docker/build-push-action@v2 with: context: . - file: ./Dockerfile - platforms: linux/amd64,linux/arm64,linux/386 push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.docker_meta.outputs.tags }} - labels: ${{ steps.docker_meta.outputs.labels }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} ``` -### Semver +| Event | Ref | Docker Tags | +|-----------------|-------------------------------|-------------------------------------| +| `pull_request` | `refs/pull/2/merge` | `pr-2` | +| `push` | `refs/heads/master` | `master` | +| `push` | `refs/heads/release/v1` | `release-v1` | +| `push tag` | `refs/tags/v1.2.3` | `v1.2.3`, `latest` | +| `push tag` | `refs/tags/v2.0.8-beta.67` | `v2.0.8-beta.67`, `latest` | -| Event | Ref | Commit SHA | Docker Tags | -|-----------------|-------------------------------|------------|-------------------------------------| -| `pull_request` | `refs/pull/2/merge` | `a123b57` | `pr-2` | -| `push` | `refs/heads/master` | `cf20257` | `master` | -| `push` | `refs/heads/my/branch` | `a5df687` | `my-branch` | -| `push tag` | `refs/tags/v1.2.3` | `ad132f5` | `1.2.3`, `1.2`, `latest` | -| `push tag` | `refs/tags/v2.0.8-beta.67` | `fc89efd` | `2.0.8-beta.67` | +### Semver ```yaml name: ci @@ -110,10 +104,14 @@ name: ci on: push: branches: - - '**' + - 'master' + - 'release/v*' tags: - 'v*' pull_request: + branches: + - 'master' + - 'release/v*' jobs: docker: @@ -124,19 +122,16 @@ jobs: uses: actions/checkout@v2 - name: Docker meta - id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 + id: meta + uses: crazy-max/ghaction-docker-meta@v2 with: images: name/app - tag-semver: | - {{version}} - {{major}}.{{minor}} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + tags: | + type=ref,event=branch + type=ref,event=tag + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} - name: Login to DockerHub if: github.event_name != 'pull_request' @@ -149,13 +144,19 @@ jobs: uses: docker/build-push-action@v2 with: context: . - file: ./Dockerfile - platforms: linux/amd64,linux/arm64,linux/386 push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.docker_meta.outputs.tags }} - labels: ${{ steps.docker_meta.outputs.labels }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} ``` +| Event | Ref | Docker Tags | +|-----------------|-------------------------------|-------------------------------------| +| `pull_request` | `refs/pull/2/merge` | `pr-2` | +| `push` | `refs/heads/master` | `master` | +| `push` | `refs/heads/release/v1` | `release-v1` | +| `push tag` | `refs/tags/v1.2.3` | `1.2.3`, `1.2`, `latest` | +| `push tag` | `refs/tags/v2.0.8-beta.67` | `2.0.8-beta.67` | + ### Bake definition This action also handles a bake definition file that can be used with the @@ -164,7 +165,6 @@ This action also handles a bake definition file that can be used with the ```hcl // docker-bake.hcl - target "ghaction-docker-meta" {} target "build" { @@ -181,10 +181,9 @@ name: ci on: push: branches: - - '**' + - 'master' tags: - 'v*' - pull_request: jobs: docker: @@ -195,40 +194,37 @@ jobs: uses: actions/checkout@v2 - name: Docker meta - id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 + id: meta + uses: crazy-max/ghaction-docker-meta@v2 with: images: name/app - tag-sha: true - tag-semver: | - {{version}} - {{major}}.{{minor}} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + tags: | + type=ref,event=branch + type=ref,event=tag + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha - name: Build uses: docker/bake-action@v1 with: files: | ./docker-bake.hcl - ${{ steps.docker_meta.outputs.bake-file }} - targets: | - build + ${{ steps.meta.outputs.bake-file }} + targets: build ``` -Content of `${{ steps.docker_meta.outputs.bake-file }}` file will look like this: +Content of `${{ steps.meta.outputs.bake-file }}` file will look like this with `refs/tags/v1.2.3` ref: ```json { "target": { "ghaction-docker-meta": { "tags": [ - "name/app:1.1.1", - "name/app:1.1", + "name/app:1.2.3", + "name/app:1.2", + "name/app:sha-90dd603", "name/app:latest" ], "labels": { @@ -236,14 +232,14 @@ Content of `${{ steps.docker_meta.outputs.bake-file }}` file will look like this "org.opencontainers.image.description": "This your first repo!", "org.opencontainers.image.url": "https://github.com/octocat/Hello-World", "org.opencontainers.image.source": "https://github.com/octocat/Hello-World", - "org.opencontainers.image.version": "1.1.1", + "org.opencontainers.image.version": "1.2.3", "org.opencontainers.image.created": "2020-01-10T00:30:00.000Z", "org.opencontainers.image.revision": "90dd6032fac8bda1b6c4436a2e65de27961ed071", "org.opencontainers.image.licenses": "MIT" }, "args": { "DOCKER_META_IMAGES": "name/app", - "DOCKER_META_VERSION": "1.1.1" + "DOCKER_META_VERSION": "1.2.3" } } } @@ -272,22 +268,12 @@ Following inputs can be used as `step.with` keys | Name | Type | Description | |---------------------|----------|------------------------------------| | `images` | List/CSV | List of Docker images to use as base name for tags | -| `tag-sha` | Bool | Add git short commit as Docker tag (default `false`) | -| `tag-edge` | Bool | Enable edge branch tagging (default `false`) | -| `tag-edge-branch` | String | Branch that will be tagged as edge (default `repo.default_branch`) | -| `tag-semver` | List/CSV | Handle Git tag as semver [template](#handle-semver-tag) if possible | -| `tag-match` | String | RegExp to match against a Git tag and use first match as Docker tag | -| `tag-match-group` | Number | Group to get if `tag-match` matches (default `0`) | -| `tag-latest` | Bool | Set `latest` Docker tag if `tag-semver`, `tag-match` or Git tag event occurs (default `true`) | -| `tag-schedule` | String | [Template](#schedule-tag) to apply to schedule tag (default `nightly`) | -| `tag-custom` | List/CSV | List of custom tags | -| `tag-custom-only` | Bool | Only use `tag-custom` as Docker tags | -| `label-custom` | List | List of custom labels | +| `tags` | List | List of [tags](#tags-input) as key-value pair attributes | +| `flavor` | List | [Flavor](#flavor-input) to apply | +| `labels` | List | List of custom labels | | `sep-tags` | String | Separator to use for tags output (default `\n`) | | `sep-labels` | String | Separator to use for labels output (default `\n`) | -> `tag-semver` and `tag-match` are mutually exclusive - ### outputs Following outputs are available @@ -299,59 +285,269 @@ Following outputs are available | `labels` | String | Docker labels | | `bake-file` | File | [Bake definition file](https://github.com/docker/buildx#file-definition) path | -## Notes +## `flavor` input -### Latest tag +`flavor` defines a global behavior for [`tags`](#tags-input): -Latest Docker tag will be generated by default on `push tag` event. If for example you push the `v1.2.3` Git tag, -you will have at the output of this action the Docker tags `v1.2.3` and `latest`. But you can allow the latest tag to be -generated only if `tag-semver` is a valid [semver](https://semver.org/) or if Git tag matches a regular expression -with the [`tag-match` input](#tag-match-examples). Can be disabled if `tag-latest` is `false`. - -### Handle semver tag - -If Git tag is a valid [semver](https://semver.org/) you can handle it to output multi Docker tags at once. -`tag-semver` supports multi-line [Handlebars template](https://handlebarsjs.com/guide/) with the following inputs: - -| Git tag | `tag-semver` | Valid | Output tags | Output version | -|--------------------|----------------------------------------------------------|--------------------|----------------------------|------------------------------| -| `v1.2.3` | `{{raw}}` | :white_check_mark: | `v1.2.3`, `latest` | `v1.2.3` | -| `v1.2.3` | `{{version}}` | :white_check_mark: | `1.2.3`, `latest` | `1.2.3` | -| `v1.2.3` | `{{major}}.{{minor}}` | :white_check_mark: | `1.2`, `latest` | `1.2` | -| `v1.2.3` | `v{{major}}` | :white_check_mark: | `v1`, `latest` | `v1` | -| `v1.2.3` | `{{minor}}` | :white_check_mark: | `2`, `latest` | `2` | -| `v1.2.3` | `{{patch}}` | :white_check_mark: | `3`, `latest` | `3` | -| `v1.2.3` | `{{major}}.{{minor}}`
`{{major}}.{{minor}}.{{patch}}` | :white_check_mark: | `1.2`, `1.2.3`, `latest` | `1.2`* | -| `v2.0.8-beta.67` | `{{raw}}` | :white_check_mark: | `2.0.8-beta.67`** | `2.0.8-beta.67` | -| `v2.0.8-beta.67` | `{{version}}` | :white_check_mark: | `2.0.8-beta.67` | `2.0.8-beta.67` | -| `v2.0.8-beta.67` | `{{major}}.{{minor}}` | :white_check_mark: | `2.0.8-beta.67`** | `2.0.8-beta.67` | -| `release1` | `{{raw}}` | :x: | `release1` | `release1` | - -> *First occurrence of `tag-semver` will be taken as `output.version` - -> **Pre-release (rc, beta, alpha) will only extend `{{version}}` as tag because they are updated frequently, -> and contain many breaking changes that are (by the author's design) not yet fit for public consumption. +```yaml +flavor: | + latest=auto + prefix= + suffix= +``` + +* `latest=`: Handle [latest tag](#latest-tag) (default `auto`) +* `prefix=`: A global prefix for each generated tag +* `suffix=`: A global suffix for each generated tag + +## `tags` input + +`tags` is the core input of this action as everything related to it will reflect the output metadata. This one is in +the form of a key-value pair list in CSV format to remove limitations intrinsically linked to GitHub Actions +(only string format is handled in the input fields). Here is an example: -### `tag-match` examples +```yaml +tags: | + type=schedule + type=ref,event=branch + type=ref,event=tag + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha +``` + +Each entry is defined by a `type`, which are: + +* [`type=schedule`](#typeschedule) +* [`type=semver`](#typesemver) +* [`type=match`](#typematch) +* [`type=edge`](#typeedge) +* [`type=ref`](#typeref) +* [`type=raw`](#typeraw) +* [`type=sha`](#typesha) + +And global attributes: + +* `enable=` enable this entry (default `true`) +* `priority=` priority to manage the order of tags +* `prefix=` add prefix +* `suffix=` add suffix + +Default entries if `tags` input is empty: -| Git tag | `tag-match` | `tag-match-group` | Match | Output tags | Output version | -|-------------------------|------------------------------------|-------------------|----------------------|---------------------------|------------------------------| -| `v1.2.3` | `\d{1,3}.\d{1,3}.\d{1,3}` | `0` | :white_check_mark: | `1.2.3`, `latest` | `1.2.3` | -| `v2.0.8-beta.67` | `v(.*)` | `1` | :white_check_mark: | `2.0.8-beta.67`, `latest` | `2.0.8-beta.67` | -| `v2.0.8-beta.67` | `v(\d.\d)` | `1` | :white_check_mark: | `2.0`, `latest` | `2.0` | -| `release1` | `\d{1,3}.\d{1,3}` | `0` | :x: | `release1` | `release1` | -| `20200110-RC2` | `\d+` | `0` | :white_check_mark: | `20200110`, `latest` | `20200110` | +```yaml +tags: | + type=schedule + type=ref,event=branch + type=ref,event=tag + type=ref,event=pr +``` + +### `type=schedule` + +```yaml +tags: | + # minimal + type=schedule + # default + type=schedule,pattern=nightly + # handlebars + type=schedule,pattern={{date 'YYYYMMDD'}} +``` -### Schedule tag +Will be used on [schedule event](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#schedule). -`tag-schedule` is specially crafted input to support [Handlebars template](https://handlebarsjs.com/guide/) with +`pattern` is a specially crafted attribute to support [Handlebars template](https://handlebarsjs.com/guide/) with the following expressions: +* `date 'format'` ; render date by its [moment format](https://momentjs.com/docs/#/displaying/format/) -| Expression | Example | Description | -|-------------------------|-------------------------------------------|------------------------------------------| -| `{{date 'format'}}` | `{{date 'YYYYMMDD'}}` > `20200110` | Render date by its [moment format](https://momentjs.com/docs/#/displaying/format/) +| Pattern | Output | +|--------------------------|----------------------| +| `nightly` | `nightly` | +| `{{date 'YYYYMMDD'}}` | `20210326` | + +Extended attributes and default values: + +```yaml +tags: | + type=schedule,enable=true,priority=1000,prefix=,suffix=,pattern=nightly +``` + +### `type=semver` + +```yaml +tags: | + # minimal + type=semver,pattern={{version}} +``` + +Will be used on a [push tag event](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push) +and requires a valid Git tag [semver](https://semver.org/). + +`pattern` attribute supports [Handlebars template](https://handlebarsjs.com/guide/) with the following expressions: +* `raw` ; the actual semver +* `version` ; shorthand for `{{major}}.{{minor}}.{{patch}}` (can include pre-release) +* `major` ; major version identifier +* `minor` ; minor version identifier +* `patch` ; patch version identifier + +| Git tag | Pattern | Output | +|--------------------|----------------------------------------------------------|----------------------| +| `v1.2.3` | `{{raw}}` | `v1.2.3` | +| `v1.2.3` | `{{version}}` | `1.2.3` | +| `v1.2.3` | `{{major}}.{{minor}}` | `1.2` | +| `v1.2.3` | `v{{major}}` | `v1` | +| `v1.2.3` | `{{minor}}` | `2` | +| `v1.2.3` | `{{patch}}` | `3` | +| `v2.0.8-beta.67` | `{{raw}}` | `2.0.8-beta.67`* | +| `v2.0.8-beta.67` | `{{version}}` | `2.0.8-beta.67` | +| `v2.0.8-beta.67` | `{{major}}.{{minor}}` | `2.0.8-beta.67`* | + +> *Pre-release (rc, beta, alpha) will only extend `{{version}}` as tag because they are updated frequently, +> and contain many breaking changes that are (by the author's design) not yet fit for public consumption. + +Extended attributes and default values: + +```yaml +tags: | + type=semver,enable=true,priority=900,prefix=,suffix=,pattern= +``` + +### `type=match` + +```yaml +tags: | + # minimal + type=match,pattern=\d{8} + # double quotes if comma in pattern + type=match,"pattern=\d{1,3}.\d{1,3}.\d{1,3}" + # define match group + type=match,pattern=v(.*),group=1 +``` + +Can create a regular expression for matching Git tag with a pattern and capturing group. Will be used on a +[push tag event](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push). + +| Git tag | Pattern | Group | Output | +|-------------------------|-------------------------------|---------|------------------------| +| `v1.2.3` | `\d{1,3}.\d{1,3}.\d{1,3}` | `0` | `1.2.3` | +| `v2.0.8-beta.67` | `v(.*)` | `1` | `2.0.8-beta.67` | +| `v2.0.8-beta.67` | `v(\d.\d)` | `1` | `2.0` | +| `20200110-RC2` | `\d+` | `0` | `20200110` | + +Extended attributes and default values: + +```yaml +tags: | + type=group,enable=true,priority=800,prefix=,suffix=,pattern=,group=0 +``` + +### `type=edge` + +```yaml +tags: | + # minimal + type=edge + # define default branch + type=edge,branch=main +``` + +An `edge` tag reflects the last commit of the active branch on your Git repository. I usually prefer to use `edge` +as a Docker tag for a better distinction or common pattern. This is also used by official images +like [Alpine](https://hub.docker.com/_/alpine). + +Extended attributes and default values: + +```yaml +tags: | + type=edge,enable=true,priority=700,prefix=,suffix=,branch=$repo.default_branch +``` + +### `type=ref` + +```yaml +tags: | + # minimal branch event + type=ref,event=branch + # minimal tag event + type=ref,event=tag + # minimal pull request event + type=ref,event=pr +``` + +This type handles Git ref (or reference) for the following events: +* `branch` ; eg. `refs/heads/master` +* `tag` ; eg. `refs/tags/v1.0.0` +* `pr` ; eg. `refs/pull/318/merge` + +| Event | Ref | Output | +|-----------------|-------------------------------|-------------------------------| +| `pull_request` | `refs/pull/2/merge` | `pr-2` | +| `push` | `refs/heads/master` | `master` | +| `push` | `refs/heads/my/branch` | `my-branch` | +| `push tag` | `refs/tags/v1.2.3` | `v1.2.3` | +| `push tag` | `refs/tags/v2.0.8-beta.67` | `v2.0.8-beta.67` | + +Extended attributes and default values: + +```yaml +tags: | + # event branch + type=ref,enable=true,priority=600,prefix=,suffix=,event= + # event tag + type=ref,enable=true,priority=600,prefix=,suffix=,event= + # event pr + type=ref,enable=true,priority=600,prefix=pr-,suffix=,event= +``` + +### `type=raw` + +```yaml +tags: | + type=raw,value=mytag1 + type=raw,value=mytag2 + # or + type=raw,mytag1 + type=raw,mytag2 + # or + mytag1 + mytag2 +``` + +Extended attributes and default values: + +```yaml +tags: | + type=raw,enable=true,priority=200,prefix=,suffix=,value=mytag1 +``` + +### `type=sha` + +```yaml +tags: | + # minimal + type=sha +``` + +Output Git short commit as Docker tag like `sha-ad132f5`. + +Extended attributes and default values: + +```yaml +tags: | + type=sha,enable=true,priority=100,prefix=sha-,suffix= +``` + +## Notes + +### Latest tag -You can find more examples in the [CI workflow](.github/workflows/ci.yml). +`latest` tag is handled through the [`flavor` input](#flavor-input). It will be generated by default (`auto` mode) for: +* [`type=ref,event=tag`](#typeref) +* [`type=semver,pattern=...`](#typesemver) +* [`type=match,pattern=...`](#typematch) ### Overwrite labels @@ -362,10 +558,10 @@ labels generated are not suitable, you can overwrite them like this: - name: Docker meta id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 + uses: crazy-max/ghaction-docker-meta@v2 with: images: name/app - label-custom: | + labels: | maintainer=CrazyMax org.opencontainers.image.title=MyCustomTitle org.opencontainers.image.description=Another description