diff --git a/README.md b/README.md index b9973393..69fc3167 100644 --- a/README.md +++ b/README.md @@ -1,1053 +1,1057 @@ -[![GitHub release](https://img.shields.io/github/release/docker/metadata-action.svg?style=flat-square)](https://github.com/docker/metadata-action/releases/latest) -[![GitHub marketplace](https://img.shields.io/badge/marketplace-docker--metadata--action-blue?logo=github&style=flat-square)](https://github.com/marketplace/actions/docker-metadata-action) -[![CI workflow](https://img.shields.io/github/actions/workflow/status/docker/metadata-action/ci.yml?branch=master&label=ci&logo=github&style=flat-square)](https://github.com/docker/metadata-action/actions?workflow=ci) -[![Test workflow](https://img.shields.io/github/actions/workflow/status/docker/metadata-action/test.yml?branch=master&label=test&logo=github&style=flat-square)](https://github.com/docker/metadata-action/actions?workflow=test) -[![Codecov](https://img.shields.io/codecov/c/github/docker/metadata-action?logo=codecov&style=flat-square)](https://codecov.io/gh/docker/metadata-action) - -## About - -GitHub Action to extract metadata from Git reference and GitHub events. This action -is particularly useful if used with [Docker Build Push](https://github.com/docker/build-push-action) -action to tag and label Docker images. - -![Screenshot](.github/metadata-action.png) - -___ - -* [Usage](#usage) - * [Basic](#basic) - * [Semver](#semver) - * [Bake definition](#bake-definition) -* [Customizing](#customizing) - * [inputs](#inputs) - * [outputs](#outputs) - * [environment variables](#environment-variables) -* [`context` input](#context-input) -* [`images` input](#images-input) -* [`flavor` input](#flavor-input) -* [`tags` input](#tags-input) - * [`type=schedule`](#typeschedule) - * [`type=semver`](#typesemver) - * [`type=pep440`](#typepep440) - * [`type=match`](#typematch) - * [`type=edge`](#typeedge) - * [`type=ref`](#typeref) - * [`type=raw`](#typeraw) - * [`type=sha`](#typesha) -* [Notes](#notes) - * [Image name and tag sanitization](#image-name-and-tag-sanitization) - * [Latest tag](#latest-tag) - * [`priority` attribute](#priority-attribute) - * [Global expressions](#global-expressions) - * [`{{branch}}`](#branch) - * [`{{tag}}`](#tag) - * [`{{sha}}`](#sha) - * [`{{base_ref}}`](#base_ref) - * [`{{is_default_branch}}`](#is_default_branch) - * [`{{is_not_default_branch}}`](#is_not_default_branch) - * [`{{date '' tz=''}}`](#date-format-tztimezone) - * [`{{commit_date '' tz=''}}`](#commit_date-format-tztimezone) - * [Major version zero](#major-version-zero) - * [JSON output object](#json-output-object) - * [Overwrite labels and annotations](#overwrite-labels-and-annotations) - * [Annotations](#annotations) -* [Contributing](#contributing) - -## Usage - -### Basic - -```yaml -name: ci - -on: - workflow_dispatch: - push: - branches: - - 'master' - tags: - - 'v*' - pull_request: - branches: - - 'master' - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - - name: Checkout - uses: actions/checkout@v6 - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: name/app - - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - push: ${{ github.event_name != 'pull_request' }} - 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/releases/v1` | `releases-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` | -| `workflow_dispatch` | `refs/heads/master` | `master` | - -### Semver - -```yaml -name: ci - -on: - push: - branches: - - 'master' - tags: - - 'v*' - pull_request: - branches: - - 'master' - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - - name: Checkout - uses: actions/checkout@v6 - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - name/app - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v6 - with: - context: . - push: ${{ github.event_name != 'pull_request' }} - 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/releases/v1` | `releases-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 -[Docker Bake action](https://github.com/docker/bake-action). You just have to -declare an empty target named `docker-metadata-action` and inherit from it. - -```hcl -// docker-bake.hcl -target "docker-metadata-action" {} - -target "build" { - inherits = ["docker-metadata-action"] - context = "./" - dockerfile = "Dockerfile" - platforms = [ - "linux/amd64", - "linux/arm/v6", - "linux/arm/v7", - "linux/arm64", - "linux/386" - ] -} -``` - -```yaml -name: ci - -on: - push: - branches: - - 'master' - tags: - - 'v*' - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - name/app - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha - - - name: Build - uses: docker/bake-action@v6 - with: - files: | - ./docker-bake.hcl - cwd://${{ steps.meta.outputs.bake-file }} - targets: build -``` - -Content of `${{ steps.meta.outputs.bake-file }}` file, combining tags and -labels, will look like this with `refs/tags/v1.2.3` ref: - -```json -{ - "target": { - "docker-metadata-action": { - "tags": [ - "name/app:1.2.3", - "name/app:1.2", - "name/app:sha-90dd603", - "name/app:latest" - ], - "labels": { - "org.opencontainers.image.title": "Hello-World", - "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.2.3", - "org.opencontainers.image.created": "2020-01-10T00:30:00.000Z", - "org.opencontainers.image.revision": "860c1904a1ce19322e91ac35af1ab07466440c37", - "org.opencontainers.image.licenses": "MIT" - }, - "args": { - "DOCKER_META_IMAGES": "name/app", - "DOCKER_META_VERSION": "1.2.3" - } - } - } -} -``` - -You can also use the `bake-file-tags` and `bake-file-labels` outputs if you -just want to use tags and/or labels respectively. The following example is -similar to the previous one: - -```yaml - - - name: Build - uses: docker/bake-action@v6 - with: - files: | - ./docker-bake.hcl - cwd://${{ steps.meta.outputs.bake-file-tags }} - cwd://${{ steps.meta.outputs.bake-file-labels }} - targets: build -``` - -## Customizing - -### inputs - -The following inputs can be used as `step.with` keys: - -> [!NOTE] -> `List` type is a newline-delimited string -> ```yaml -> labels: | -> org.opencontainers.image.title=MyCustomTitle -> org.opencontainers.image.description=Another description -> org.opencontainers.image.vendor=MyCompany -> ``` - -| Name | Type | Description | -|-------------------|--------|------------------------------------------------------------------------------| -| `context` | String | Where to get context data. Allowed options are: `workflow` (default), `git`. | -| `images` | List | List of Docker images to use as base name for tags | -| `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 | -| `annotations` | List | List of custom annotations | -| `sep-tags` | String | Separator to use for tags output (default `\n`) | -| `sep-labels` | String | Separator to use for labels output (default `\n`) | -| `sep-annotations` | String | Separator to use for annotations output (default `\n`) | -| `bake-target` | String | Bake target name (default `docker-metadata-action`) | - -### outputs - -The following outputs are available: - -| Name | Type | Description | -|-------------------------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `version` | String | Docker image version | -| `tags` | String | Docker tags | -| `tag-names` | String | Docker tag names without image base name | -| `labels` | String | Docker labels | -| `annotations` | String | [Annotations](https://github.com/moby/buildkit/blob/master/docs/annotations.md) | -| `json` | String | JSON output of tags and labels | -| `bake-file-tags` | File | [Bake file definition](https://docs.docker.com/build/bake/reference/) path with tags | -| `bake-file-labels` | File | [Bake file definition](https://docs.docker.com/build/bake/reference/) path with labels | -| `bake-file-annotations` | File | [Bake file definition](https://docs.docker.com/build/bake/reference/) path with [annotations](https://github.com/moby/buildkit/blob/master/docs/annotations.md) | - -Alternatively, each output is also exported as an environment variable when `DOCKER_METADATA_SET_OUTPUT_ENV` is `true`: - -* `DOCKER_METADATA_OUTPUT_VERSION` -* `DOCKER_METADATA_OUTPUT_TAGS` -* `DOCKER_METADATA_OUTPUT_LABELS` -* `DOCKER_METADATA_OUTPUT_ANNOTATIONS` -* `DOCKER_METADATA_OUTPUT_JSON` -* `DOCKER_METADATA_OUTPUT_BAKE_FILE_TAGS` -* `DOCKER_METADATA_OUTPUT_BAKE_FILE_LABELS` -* `DOCKER_METADATA_OUTPUT_BAKE_FILE_ANNOTATIONS` - -So it can be used with our [Docker Build Push action](https://github.com/docker/build-push-action/): - -```yaml -- uses: docker/build-push-action@v6 - with: - build-args: | - DOCKER_METADATA_OUTPUT_JSON -``` - -### environment variables - -| Name | Type | Description | -|--------------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------| -| `DOCKER_METADATA_PR_HEAD_SHA` | Bool | If `true`, set associated head SHA instead of commit SHA that triggered the workflow on pull request event | -| `DOCKER_METADATA_SHORT_SHA_LENGTH` | Number | Specifies the length of the [short commit SHA](#typesha) to ensure uniqueness. Default is `7`, but can be increased for larger repositories. | -| `DOCKER_METADATA_ANNOTATIONS_LEVELS` | String | Comma separated list of annotations levels to set for annotations output separated (default `manifest`) | -| `DOCKER_METADATA_SET_OUTPUT_ENV` | Bool | If `true`, sets each output as an environment variable (default `true`) | - -## `context` input - -`context` defines where to get context metadata: - -```yaml -# default -context: workflow -# or -context: git -``` - -* `workflow`: Get context metadata from the workflow (GitHub context). See https://docs.github.com/en/actions/learn-github-actions/contexts#github-context -* `git`: Get context metadata from the workflow and overrides some of them with current Git context, such as `ref` and `sha`. - -## `images` input - -`images` defines a list of Docker images to use as base name for [`tags`](#tags-input): - -```yaml -images: | - name/foo - ghcr.io/name/bar - # or - name=name/foo - name=ghcr.io/name/bar -``` - -Extended attributes and default values: - -```yaml -images: | - name=,enable=true -``` - -* `name=` image base name -* `enable=` enable this entry (default `true`) - -If `images` is empty, tags will be generated without base name. - -## `flavor` input - -`flavor` defines a global behavior for [`tags`](#tags-input): - -```yaml -flavor: | - latest=auto - prefix= - suffix= -``` - -* `latest=`: Handle [latest tag](#latest-tag) (default `auto`) -* `prefix=,onlatest=`: A global prefix for each generated - tag and optionally for `latest` -* `suffix=,onlatest=`: A global suffix for each generated - tag and optionally for `latest` - -## `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: - -```yaml -tags: | - type=schedule - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=ref,event=branch - type=ref,event=pr - type=sha -``` - -Each entry is defined by a `type`, which are: - -* [`type=schedule`](#typeschedule) -* [`type=semver`](#typesemver) -* [`type=pep440`](#typepep440) -* [`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=` set tag [priority](#priority-attribute) order -* `prefix=` add prefix -* `suffix=` add suffix - -Default entries if `tags` input is empty: - -```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'}} - # handlebars with timezone - type=schedule,pattern={{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}} -``` - -Will be used on [schedule event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule). - -`pattern` is a specially crafted attribute to support [Handlebars' template](https://handlebarsjs.com/guide/) -with the following expressions: - -* `date 'format' tz='Timezone'` ; render date by its [moment format](https://momentjs.com/docs/#/displaying/format/). - Default `tz` is UTC. - -| Pattern | Output | -|----------------------------------------------|-------------------| -| `nightly` | `nightly` | -| `{{date 'YYYYMMDD'}}` | `20200110` | -| `{{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}` | `20200110-093000` | - -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}} - # use custom value instead of git tag - type=semver,pattern={{version}},value=v1.0.0 - # use custom value and match part of it - type=semver,pattern={{version}},value=p1/v1.0.0,match=v(\d.\d.\d)$ -``` - -Will be used on a [push tag event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push) -and requires a valid [semver](https://semver.org/) Git tag, but you can also -use a custom value through `value` attribute. - -`pattern` attribute supports [Handlebars template](https://handlebarsjs.com/guide/) -with the following expressions: - -* `raw` ; the actual tag -* `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 | Match | 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` | -| `p1/v1.2.3` | `{{version}}` | `v(\d.\d.\d)$` | `1.2.3` | -| `v2.0.8-beta.67` | `{{raw}}` | | `v2.0.8-beta.67` | -| `v2.0.8-beta.67` | `{{version}}` | | `2.0.8-beta.67` | -| `v2.0.8-beta.67` | `{{major}}` | | `2.0.8-beta.67`* | -| `v2.0.8-beta.67` | `{{major}}.{{minor}}` | | `2.0.8-beta.67`* | - -> [!IMPORTANT] -> *Pre-release (rc, beta, alpha) will only extend `{{version}}` (or `{{raw}}` -> if specified) 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=,value=,match= -``` - -### `type=pep440` - -```yaml -tags: | - # minimal - type=pep440,pattern={{version}} - # use custom value instead of git tag - type=pep440,pattern={{version}},value=1.0.0 - # use custom value and match part of it - type=pep440,pattern={{version}},value=p1/v1.0.0,match=v(\d.\d.\d)$ -``` - -Will be used on a [push tag event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push) -and requires a Git tag that conforms to [PEP 440](https://www.python.org/dev/peps/pep-0440/), -but you can also use a custom value through `value` attribute. - -`pattern` attribute supports [Handlebars template](https://handlebarsjs.com/guide/) -with the following expressions: - -* `raw` ; the actual tag -* `version` ; cleaned version -* `major` ; major version identifier -* `minor` ; minor version identifier -* `patch` ; patch version identifier - -| Git tag | Pattern | Match | Output | -|--------------|-----------------------|----------------|----------------| -| `1.2.3` | `{{raw}}` | | `1.2.3` | -| `1.2.3` | `{{version}}` | | `1.2.3` | -| `v1.2.3` | `{{version}}` | | `1.2.3` | -| `1.2.3` | `{{major}}.{{minor}}` | | `1.2` | -| `1.2.3` | `v{{major}}` | | `v1` | -| `v1.2.3rc2` | `{{raw}}` | | `v1.2.3rc2` | -| `1.2.3rc2` | `{{version}}` | | `1.2.3rc2` | -| `p1/v1.2.3` | `{{version}}` | `v(\d.\d.\d)$` | `1.2.3` | -| `1.2.3rc2` | `{{major}}.{{minor}}` | | `1.2.3rc2`* | -| `1.2.3post1` | `{{major}}.{{minor}}` | | `1.2.3.post1`* | -| `1.2.3beta2` | `{{major}}.{{minor}}` | | `1.2.3b2`* | -| `1.0dev4` | `{{major}}.{{minor}}` | | `1.0.dev4`* | - -> [!IMPORTANT] -> *dev/pre/post release will only extend `{{version}}` (or `{{raw}}` if -> specified) 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=pep440,enable=true,priority=900,prefix=,suffix=,pattern=,value= -``` - -### `type=match` - -```yaml -tags: | - # minimal - type=match,pattern=\d.\d.\d - # define match group - type=match,pattern=v(.*),group=1 - # use custom value instead of git tag - type=match,pattern=v(.*),group=1,value=v1.0.0 -``` - -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/using-workflows/events-that-trigger-workflows#push) -but, you can also use a custom value through `value` attribute. - -| Git tag | Pattern | Group | Output | -|-------------------------|------------------|---------|------------------------| -| `v1.2.3` | `\d.\d.\d` | `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` | -| `p1/v1.2.3` | `p1/v(\d.\d.\d)` | `1` | `1.2.3` | - -Extended attributes and default values: - -```yaml -tags: | - type=match,enable=true,priority=800,prefix=,suffix=,pattern=,group=0,value= -``` - -### `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: | - # branch event - type=ref,event=branch - # tag event - type=ref,event=tag - # 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` | -| `workflow_dispatch` | `refs/heads/master` | `master` | - -Extended attributes and default values: - -```yaml -tags: | - # branch event - type=ref,enable=true,priority=600,prefix=,suffix=,event=branch - # tag event - type=ref,enable=true,priority=600,prefix=,suffix=,event=tag - # pull request event - type=ref,enable=true,priority=600,prefix=pr-,suffix=,event=pr -``` - -### `type=raw` - -```yaml -tags: | - type=raw,value=foo - type=raw,value=bar - # or - type=raw,foo - type=raw,bar - # or - foo - bar -``` - -Output custom tags according to your needs. - -Extended attributes and default values: - -```yaml -tags: | - type=raw,enable=true,priority=200,prefix=,suffix=,value= -``` - -### `type=sha` - -```yaml -tags: | - # minimal (short sha) - type=sha - # full length sha - type=sha,format=long -``` - -Output Git short commit (or long if specified) as Docker tag like -`sha-860c190`. - -By default, the length of the short commit SHA is `7` characters. You can -increase this length for larger repositories by setting the -[`DOCKER_METADATA_SHORT_SHA_LENGTH` environment variable](#environment-variables): - -```yaml - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - name/app - tags: | - type=sha - env: - DOCKER_METADATA_SHORT_SHA_LENGTH: 12 -``` - -Extended attributes and default values: - -```yaml -tags: | - type=sha,enable=true,priority=100,prefix=sha-,suffix=,format=short -``` - -## Notes - -### Image name and tag sanitization - -In order to comply with [the specification](https://docs.docker.com/engine/reference/commandline/tag/#description), -the image name components may contain lowercase letters, digits and separators. -A separator is defined as a period, one or two underscores, or one or more -dashes. A name component may not start or end with a separator. - -A tag name must be a valid ASCII chars sequences and may contain lowercase and -uppercase letters, digits, underscores, periods and dashes. A tag name may not -start with a period or a dash and may contain a maximum of 128 characters. - -To ease the integration in your workflow, this action will automatically: - -* Lowercase the image name -* Replace invalid chars sequences with `-` for tags - -### Latest tag - -`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=pep440,pattern=...`](#typepep440) -* [`type=match,pattern=...`](#typematch) - -For conditionally tagging with latest for a specific branch name, e.g. if your -default branch name is not `master`, use `type=raw` with a boolean expression: - -```yaml -tags: | - # set latest tag for master branch - type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} -``` - -You can also use the [`{{is_default_branch}}` global expression](#is_default_branch) -to conditionally tag with latest for the default branch: - -```yaml -tags: | - # set latest tag for default branch - type=raw,value=latest,enable={{is_default_branch}} -``` - -### `priority` attribute - -`priority=` attribute is used to sort tags in the final list. The higher -the value, the higher the priority. The first tag in the list (higher priority) -will be used as the image version for generated OCI label and [`version` output](#outputs). -Each tags `type` attribute has a default priority: - -| Attribute | Default priority | -|------------|------------------| -| `schedule` | `1000` | -| `semver` | `900` | -| `pep440` | `900` | -| `match` | `800` | -| `edge` | `700` | -| `ref` | `600` | -| `raw` | `200` | -| `sha` | `100` | - -### Global expressions - -The following [Handlebars' template](https://handlebarsjs.com/guide/) expressions -for `prefix`, `suffix`, `value` and `enable` attributes of `tags` input are -available: - -```yaml -tags: | - # dynamically set the branch name as a prefix - type=sha,prefix={{branch}}- - # dynamically set the branch name and sha as a custom tag - type=raw,value=mytag-{{branch}}-{{sha}} -``` - -They can also be applied to `labels` and `annotations` inputs: - -```yaml -labels: | - org.opencontainers.image.created={{commit_date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}} -``` - -#### `{{branch}}` - -Returns the branch name that triggered the workflow run. Will be empty if not -a branch reference: - -| Event | Ref | Output | -|----------------|------------------------|-------------| -| `pull_request` | `refs/pull/2/merge` | | -| `push` | `refs/heads/master` | `master` | -| `push` | `refs/heads/my/branch` | `my-branch` | -| `push tag` | `refs/tags/v1.2.3` | | - -#### `{{tag}}` - -Returns the tag name that triggered the workflow run. Will be empty if not a -tag reference: - -| Event | Ref | Output | -|-----------------|-------------------------------|--------------------| -| `pull_request` | `refs/pull/2/merge` | | -| `push` | `refs/heads/master` | | -| `push` | `refs/heads/my/branch` | | -| `push tag` | `refs/tags/v1.2.3` | `v1.2.3` | - -#### `{{sha}}` - -Returns the short commit SHA that triggered the workflow run (e.g., `90dd603`). - -#### `{{base_ref}}` - -Returns the base ref or target branch of the pull request that triggered the -workflow run. Will be empty for a branch reference: - -| Event | Ref | Output | -|----------------|-------------------------------|--------------------| -| `pull_request` | `refs/pull/2/merge` | `master` | -| `push` | `refs/heads/master` | | -| `push` | `refs/heads/my/branch` | | -| `push tag`* | `refs/tags/v1.2.3` | `master` | - -> [!IMPORTANT] -> *`base_ref` is available in the push payload but doesn't always seem to -> return the expected branch when the push tag event occurs. It's also -> [not documented in GitHub docs](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push). -> We keep it for backward compatibility, but it's **not recommended relying on it**. -> More context in [#192](https://github.com/docker/metadata-action/pull/192#discussion_r854673012). - -#### `{{is_default_branch}}` - -Returns `true` if the branch that triggered the workflow run is the default -one, otherwise `false`. - -#### `{{is_not_default_branch}}` - -Returns `true` if the branch that triggered the workflow run is not the default -one, otherwise `false`. - -#### `{{date '' tz=''}}` - -Returns the current date rendered by its [moment format](https://momentjs.com/docs/#/displaying/format/). -Default `tz` is UTC. - -| Expression | Output example | -|----------------------------------------------|-----------------------------------------| -| `{{date 'YYYYMMDD'}}` | `20200110` | -| `{{date 'dddd, MMMM Do YYYY, h:mm:ss a'}}` | `Friday, January 10th 2020, 3:25:50 pm` | -| `{{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}` | `20200110-093000` | - -#### `{{commit_date '' tz=''}}` - -Returns the date when the current git commit is committed, rendered by its -[moment format](https://momentjs.com/docs/#/displaying/format/). It falls back -to the current date if the commit date is not available. - -Default `tz` is UTC. - -| Expression | Output example | -|-----------------------------------------------------|-----------------------------------------| -| `{{commit_date 'YYYYMMDD'}}` | `20200110` | -| `{{commit_date 'dddd, MMMM Do YYYY, h:mm:ss a'}}` | `Friday, January 10th 2020, 3:25:50 pm` | -| `{{commit_date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}` | `20200110-093000` | - -### Major version zero - -Major version zero (`0.y.z`) is for initial development and **may** change at -any time. This means the public API [**should not** be considered stable](https://semver.org/#spec-item-4). - -In this case, Docker tag `0` **should not** be generated if you're using [`type=semver`](#typesemver) -with `{{major}}` pattern. You can manage this behavior like this: - -```yaml -# refs/tags/v0.1.2 -tags: | - # output 0.1.2 - type=semver,pattern={{version}} - # output 0.1 - type=semver,pattern={{major}}.{{minor}} - # disabled if major zero - type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }} -``` - -### JSON output object - -The `json` output is a JSON object composed of the generated tags and labels so -that you can reuse them further in your workflow using the [`fromJSON` function](https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson): - -```yaml - - - name: Docker meta - uses: docker/metadata-action@v5 - id: meta - with: - images: name/app - - - name: Build and push - uses: docker/build-push-action@v6 - with: - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: | - BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} - VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} - REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} -``` - -### Overwrite labels and annotations - -If some [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/master/annotations.md) -generated are not suitable as labels/annotations, you can overwrite them like -this: - -```yaml - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: name/app - labels: | - maintainer=CrazyMax - org.opencontainers.image.title=MyCustomTitle - org.opencontainers.image.description=Another description - org.opencontainers.image.vendor=MyCompany -``` - -### Annotations - -Since Buildx 0.12, it is possible to set annotations to your image through the -`--annotation` flag. - -With the [`build-push-action`](https://github.com/docker/build-push-action/), -you can set the `annotations` input with the value of the `annotations` output -of the `metadata-action`: - -```yaml - - - name: Docker meta - uses: docker/metadata-action@v5 - with: - images: name/app - - - name: Build and push - uses: docker/build-push-action@v6 - with: - tags: ${{ steps.meta.outputs.tags }} - annotations: ${{ steps.meta.outputs.annotations }} -``` - -The same can be done with the [`bake-action`](https://github.com/docker/bake-action/): - -```yaml - - - name: Docker meta - uses: docker/metadata-action@v5 - with: - images: name/app - - - name: Build - uses: docker/bake-action@v6 - with: - files: | - ./docker-bake.hcl - cwd://${{ steps.meta.outputs.bake-file-tags }} - cwd://${{ steps.meta.outputs.bake-file-annotations }} - targets: build -``` - -Note that annotations can be attached at many different levels within a manifest. -By default, the generated annotations will be attached to image manifests, -but different registries may expect annotations at different places; -a common practice is to read annotations at _image indexes_ if present, -which are often used by multi-arch builds to index platform-specific images. -If you want to specify level(s) for your annotations, you can use the -[`DOCKER_METADATA_ANNOTATIONS_LEVELS` environment variable](#environment-variables) -with a comma separated list of all levels the annotations should be attached to (defaults to `manifest`). -The following configuration demonstrates the ability to attach annotations to both image manifests and image indexes, -though your registry may only need annotations at the index level. (That is, `index` alone may be enough.) -Please consult the documentation of your registry. - -```yaml - - - name: Docker meta - uses: docker/metadata-action@v5 - with: - images: name/app - env: - DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index - - - name: Build and push - uses: docker/build-push-action@v6 - with: - tags: ${{ steps.meta.outputs.tags }} - annotations: ${{ steps.meta.outputs.annotations }} -``` - -More information about annotations in the [BuildKit documentation](https://github.com/moby/buildkit/blob/master/docs/annotations.md). - -## Contributing - -Want to contribute? Awesome! You can find information about contributing to -this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md) +[![GitHub release](https://img.shields.io/github/release/docker/metadata-action.svg?style=flat-square)](https://github.com/docker/metadata-action/releases/latest) +[![GitHub marketplace](https://img.shields.io/badge/marketplace-docker--metadata--action-blue?logo=github&style=flat-square)](https://github.com/marketplace/actions/docker-metadata-action) +[![CI workflow](https://img.shields.io/github/actions/workflow/status/docker/metadata-action/ci.yml?branch=master&label=ci&logo=github&style=flat-square)](https://github.com/docker/metadata-action/actions?workflow=ci) +[![Test workflow](https://img.shields.io/github/actions/workflow/status/docker/metadata-action/test.yml?branch=master&label=test&logo=github&style=flat-square)](https://github.com/docker/metadata-action/actions?workflow=test) +[![Codecov](https://img.shields.io/codecov/c/github/docker/metadata-action?logo=codecov&style=flat-square)](https://codecov.io/gh/docker/metadata-action) + +## About + +GitHub Action to extract metadata from Git reference and GitHub events. This action +is particularly useful if used with [Docker Build Push](https://github.com/docker/build-push-action) +action to tag and label Docker images. + +![Screenshot](.github/metadata-action.png) + +___ + +* [Usage](#usage) + * [Basic](#basic) + * [Semver](#semver) + * [Bake definition](#bake-definition) +* [Customizing](#customizing) + * [inputs](#inputs) + * [outputs](#outputs) + * [environment variables](#environment-variables) +* [`context` input](#context-input) +* [`images` input](#images-input) +* [`flavor` input](#flavor-input) +* [`tags` input](#tags-input) + * [`type=schedule`](#typeschedule) + * [`type=semver`](#typesemver) + * [`type=pep440`](#typepep440) + * [`type=match`](#typematch) + * [`type=edge`](#typeedge) + * [`type=ref`](#typeref) + * [`type=raw`](#typeraw) + * [`type=sha`](#typesha) +* [Notes](#notes) + * [Image name and tag sanitization](#image-name-and-tag-sanitization) + * [Latest tag](#latest-tag) + * [`priority` attribute](#priority-attribute) + * [Global expressions](#global-expressions) + * [`{{branch}}`](#branch) + * [`{{tag}}`](#tag) + * [`{{sha}}`](#sha) + * [`{{base_ref}}`](#base_ref) + * [`{{is_default_branch}}`](#is_default_branch) + * [`{{is_not_default_branch}}`](#is_not_default_branch) + * [`{{date '' tz=''}}`](#date-format-tztimezone) + * [`{{commit_date '' tz=''}}`](#commit_date-format-tztimezone) + * [Major version zero](#major-version-zero) + * [JSON output object](#json-output-object) + * [Overwrite labels and annotations](#overwrite-labels-and-annotations) + * [Annotations](#annotations) +* [Contributing](#contributing) + +## Usage + +### Basic + +```yaml +name: ci + +on: + workflow_dispatch: + push: + branches: + - 'master' + tags: + - 'v*' + pull_request: + branches: + - 'master' + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v6 + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: name/app + - + name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + 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/releases/v1` | `releases-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` | +| `workflow_dispatch` | `refs/heads/master` | `master` | + +### Semver + +```yaml +name: ci + +on: + push: + branches: + - 'master' + tags: + - 'v*' + pull_request: + branches: + - 'master' + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v6 + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + name/app + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + - + name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + 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/releases/v1` | `releases-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 +[Docker Bake action](https://github.com/docker/bake-action). You just have to +declare an empty target named `docker-metadata-action` and inherit from it. + +```hcl +// docker-bake.hcl +target "docker-metadata-action" {} + +target "build" { + inherits = ["docker-metadata-action"] + context = "./" + dockerfile = "Dockerfile" + platforms = [ + "linux/amd64", + "linux/arm/v6", + "linux/arm/v7", + "linux/arm64", + "linux/386" + ] +} +``` + +```yaml +name: ci + +on: + push: + branches: + - 'master' + tags: + - 'v*' + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + name/app + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha + - + name: Build + uses: docker/bake-action@v6 + with: + files: | + ./docker-bake.hcl + cwd://${{ steps.meta.outputs.bake-file }} + targets: build +``` + +Content of `${{ steps.meta.outputs.bake-file }}` file, combining tags and +labels, will look like this with `refs/tags/v1.2.3` ref: + +```json +{ + "target": { + "docker-metadata-action": { + "tags": [ + "name/app:1.2.3", + "name/app:1.2", + "name/app:sha-90dd603", + "name/app:latest" + ], + "labels": { + "org.opencontainers.image.title": "Hello-World", + "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.2.3", + "org.opencontainers.image.created": "2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision": "860c1904a1ce19322e91ac35af1ab07466440c37", + "org.opencontainers.image.licenses": "MIT" + }, + "args": { + "DOCKER_META_IMAGES": "name/app", + "DOCKER_META_VERSION": "1.2.3" + } + } + } +} +``` + +You can also use the `bake-file-tags` and `bake-file-labels` outputs if you +just want to use tags and/or labels respectively. The following example is +similar to the previous one: + +```yaml + - + name: Build + uses: docker/bake-action@v6 + with: + files: | + ./docker-bake.hcl + cwd://${{ steps.meta.outputs.bake-file-tags }} + cwd://${{ steps.meta.outputs.bake-file-labels }} + targets: build +``` + +## Customizing + +### inputs + +The following inputs can be used as `step.with` keys: + +> [!NOTE] +> `List` type is a newline-delimited string +> ```yaml +> labels: | +> org.opencontainers.image.title=MyCustomTitle +> org.opencontainers.image.description=Another description +> org.opencontainers.image.vendor=MyCompany +> ``` + +| Name | Type | Description | +|-------------------|--------|------------------------------------------------------------------------------| +| `context` | String | Where to get context data. Allowed options are: `workflow` (default), `git`. | +| `images` | List | List of Docker images to use as base name for tags | +| `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 | +| `annotations` | List | List of custom annotations | +| `sep-tags` | String | Separator to use for tags output (default `\n`) | +| `sep-labels` | String | Separator to use for labels output (default `\n`) | +| `sep-annotations` | String | Separator to use for annotations output (default `\n`) | +| `bake-target` | String | Bake target name (default `docker-metadata-action`) | + +### outputs + +The following outputs are available: + +| Name | Type | Description | +|-------------------------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `version` | String | Docker image version | +| `tags` | String | Docker tags | +| `tag-names` | String | Docker tag names without image base name | +| `labels` | String | Docker labels | +| `annotations` | String | [Annotations](https://github.com/moby/buildkit/blob/master/docs/annotations.md) | +| `json` | String | JSON output of tags and labels | +| `bake-file-tags` | File | [Bake file definition](https://docs.docker.com/build/bake/reference/) path with tags | +| `bake-file-labels` | File | [Bake file definition](https://docs.docker.com/build/bake/reference/) path with labels | +| `bake-file-annotations` | File | [Bake file definition](https://docs.docker.com/build/bake/reference/) path with [annotations](https://github.com/moby/buildkit/blob/master/docs/annotations.md) | + +Alternatively, each output is also exported as an environment variable when `DOCKER_METADATA_SET_OUTPUT_ENV` is `true`: + +* `DOCKER_METADATA_OUTPUT_VERSION` +* `DOCKER_METADATA_OUTPUT_TAGS` +* `DOCKER_METADATA_OUTPUT_LABELS` +* `DOCKER_METADATA_OUTPUT_ANNOTATIONS` +* `DOCKER_METADATA_OUTPUT_JSON` +* `DOCKER_METADATA_OUTPUT_BAKE_FILE_TAGS` +* `DOCKER_METADATA_OUTPUT_BAKE_FILE_LABELS` +* `DOCKER_METADATA_OUTPUT_BAKE_FILE_ANNOTATIONS` + +So it can be used with our [Docker Build Push action](https://github.com/docker/build-push-action/): + +```yaml +- uses: docker/build-push-action@v6 + with: + build-args: | + DOCKER_METADATA_OUTPUT_JSON +``` + +### environment variables + +| Name | Type | Description | +|--------------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------| +| `DOCKER_METADATA_PR_HEAD_SHA` | Bool | If `true`, set associated head SHA instead of commit SHA that triggered the workflow on pull request event | +| `DOCKER_METADATA_SHORT_SHA_LENGTH` | Number | Specifies the length of the [short commit SHA](#typesha) to ensure uniqueness. Default is `7`, but can be increased for larger repositories. | +| `DOCKER_METADATA_ANNOTATIONS_LEVELS` | String | Comma separated list of annotations levels to set for annotations output separated (default `manifest`) | +| `DOCKER_METADATA_SET_OUTPUT_ENV` | Bool | If `true`, sets each output as an environment variable (default `true`) | + +## `context` input + +`context` defines where to get context metadata: + +```yaml +# default +context: workflow +# or +context: git +``` + +* `workflow`: Get context metadata from the workflow (GitHub context). See https://docs.github.com/en/actions/learn-github-actions/contexts#github-context +* `git`: Get context metadata from the workflow and overrides some of them with current Git context, such as `ref` and `sha`. + +## `images` input + +`images` defines a list of Docker images to use as base name for [`tags`](#tags-input): + +```yaml +images: | + name/foo + ghcr.io/name/bar + # or + name=name/foo + name=ghcr.io/name/bar +``` + +Extended attributes and default values: + +```yaml +images: | + name=,enable=true +``` + +* `name=` image base name +* `enable=` enable this entry (default `true`) + +If `images` is empty, tags will be generated without base name. + +## `flavor` input + +`flavor` defines a global behavior for [`tags`](#tags-input): + +```yaml +flavor: | + latest=auto + prefix= + suffix= +``` + +* `latest=`: Handle [latest tag](#latest-tag) (default `auto`) +* `prefix=,onlatest=`: A global prefix for each generated + tag and optionally for `latest` +* `suffix=,onlatest=`: A global suffix for each generated + tag and optionally for `latest` + +## `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: + +```yaml +tags: | + type=schedule + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=ref,event=branch + type=ref,event=pr + type=sha +``` + +Each entry is defined by a `type`, which are: + +* [`type=schedule`](#typeschedule) +* [`type=semver`](#typesemver) +* [`type=pep440`](#typepep440) +* [`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=` set tag [priority](#priority-attribute) order +* `prefix=` add prefix +* `suffix=` add suffix + +Default entries if `tags` input is empty: + +```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'}} + # handlebars with timezone + type=schedule,pattern={{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}} +``` + +Will be used on [schedule event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule). + +`pattern` is a specially crafted attribute to support [Handlebars' template](https://handlebarsjs.com/guide/) +with the following expressions: + +* `date 'format' tz='Timezone'` ; render date by its [moment format](https://momentjs.com/docs/#/displaying/format/). + Default `tz` is UTC. + +| Pattern | Output | +|----------------------------------------------|-------------------| +| `nightly` | `nightly` | +| `{{date 'YYYYMMDD'}}` | `20200110` | +| `{{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}` | `20200110-093000` | + +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}} + # use custom value instead of git tag + type=semver,pattern={{version}},value=v1.0.0 + # use custom value and match part of it + type=semver,pattern={{version}},value=p1/v1.0.0,match=v(\d.\d.\d)$ +``` + +Will be used on a [push tag event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push) +and requires a valid [semver](https://semver.org/) Git tag, but you can also +use a custom value through `value` attribute. + +`pattern` attribute supports [Handlebars template](https://handlebarsjs.com/guide/) +with the following expressions: + +* `raw` ; the actual tag +* `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 | Match | 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` | +| `p1/v1.2.3` | `{{version}}` | `v(\d.\d.\d)$` | `1.2.3` | +| `v2.0.8-beta.67` | `{{raw}}` | | `v2.0.8-beta.67` | +| `v2.0.8-beta.67` | `{{version}}` | | `2.0.8-beta.67` | +| `v2.0.8-beta.67` | `{{major}}` | | `2.0.8-beta.67`* | +| `v2.0.8-beta.67` | `{{major}}.{{minor}}` | | `2.0.8-beta.67`* | + +> [!IMPORTANT] +> *Pre-release (rc, beta, alpha) will only extend `{{version}}` (or `{{raw}}` +> if specified) 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=,value=,match= +``` + +### `type=pep440` + +```yaml +tags: | + # minimal + type=pep440,pattern={{version}} + # use custom value instead of git tag + type=pep440,pattern={{version}},value=1.0.0 + # use custom value and match part of it + type=pep440,pattern={{version}},value=p1/v1.0.0,match=v(\d.\d.\d)$ +``` + +Will be used on a [push tag event](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push) +and requires a Git tag that conforms to [PEP 440](https://www.python.org/dev/peps/pep-0440/), +but you can also use a custom value through `value` attribute. + +`pattern` attribute supports [Handlebars template](https://handlebarsjs.com/guide/) +with the following expressions: + +* `raw` ; the actual tag +* `version` ; cleaned version +* `major` ; major version identifier +* `minor` ; minor version identifier +* `patch` ; patch version identifier + +| Git tag | Pattern | Match | Output | +|--------------|-----------------------|----------------|----------------| +| `1.2.3` | `{{raw}}` | | `1.2.3` | +| `1.2.3` | `{{version}}` | | `1.2.3` | +| `v1.2.3` | `{{version}}` | | `1.2.3` | +| `1.2.3` | `{{major}}.{{minor}}` | | `1.2` | +| `1.2.3` | `v{{major}}` | | `v1` | +| `v1.2.3rc2` | `{{raw}}` | | `v1.2.3rc2` | +| `1.2.3rc2` | `{{version}}` | | `1.2.3rc2` | +| `p1/v1.2.3` | `{{version}}` | `v(\d.\d.\d)$` | `1.2.3` | +| `1.2.3rc2` | `{{major}}.{{minor}}` | | `1.2.3rc2`* | +| `1.2.3post1` | `{{major}}.{{minor}}` | | `1.2.3.post1`* | +| `1.2.3beta2` | `{{major}}.{{minor}}` | | `1.2.3b2`* | +| `1.0dev4` | `{{major}}.{{minor}}` | | `1.0.dev4`* | + +> [!IMPORTANT] +> *dev/pre/post release will only extend `{{version}}` (or `{{raw}}` if +> specified) 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=pep440,enable=true,priority=900,prefix=,suffix=,pattern=,value= +``` + +### `type=match` + +```yaml +tags: | + # minimal + type=match,pattern=\d.\d.\d + # define match group + type=match,pattern=v(.*),group=1 + # use custom value instead of git tag + type=match,pattern=v(.*),group=1,value=v1.0.0 +``` + +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/using-workflows/events-that-trigger-workflows#push) +but, you can also use a custom value through `value` attribute. + +| Git tag | Pattern | Group | Output | +|-------------------------|------------------|---------|------------------------| +| `v1.2.3` | `\d.\d.\d` | `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` | +| `p1/v1.2.3` | `p1/v(\d.\d.\d)` | `1` | `1.2.3` | + +Extended attributes and default values: + +```yaml +tags: | + type=match,enable=true,priority=800,prefix=,suffix=,pattern=,group=0,value= +``` + +### `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: | + # branch event + type=ref,event=branch + # tag event + type=ref,event=tag + # 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` | +| `workflow_dispatch` | `refs/heads/master` | `master` | + +Extended attributes and default values: + +```yaml +tags: | + # branch event + type=ref,enable=true,priority=600,prefix=,suffix=,event=branch + # tag event + type=ref,enable=true,priority=600,prefix=,suffix=,event=tag + # pull request event + type=ref,enable=true,priority=600,prefix=pr-,suffix=,event=pr +``` + +### `type=raw` + +```yaml +tags: | + type=raw,value=foo + type=raw,value=bar + # or + type=raw,foo + type=raw,bar + # or + foo + bar +``` + +Output custom tags according to your needs. + +Extended attributes and default values: + +```yaml +tags: | + type=raw,enable=true,priority=200,prefix=,suffix=,value= +``` + +### `type=sha` + +```yaml +tags: | + # minimal (short sha) + type=sha + # full length sha + type=sha,format=long +``` + +Output Git short commit (or long if specified) as Docker tag like +`sha-860c190`. + +By default, the length of the short commit SHA is `7` characters. You can +increase this length for larger repositories by setting the +[`DOCKER_METADATA_SHORT_SHA_LENGTH` environment variable](#environment-variables): + +```yaml + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + name/app + tags: | + type=sha + env: + DOCKER_METADATA_SHORT_SHA_LENGTH: 12 +``` + +Extended attributes and default values: + +```yaml +tags: | + type=sha,enable=true,priority=100,prefix=sha-,suffix=,format=short +``` + +## Notes + +### Image name and tag sanitization + +In order to comply with [the specification](https://docs.docker.com/engine/reference/commandline/tag/#description), +the image name components may contain lowercase letters, digits and separators. +A separator is defined as a period, one or two underscores, or one or more +dashes. A name component may not start or end with a separator. + +A tag name must be a valid ASCII chars sequences and may contain lowercase and +uppercase letters, digits, underscores, periods and dashes. A tag name may not +start with a period or a dash and may contain a maximum of 128 characters. + +To ease the integration in your workflow, this action will automatically: + +* Lowercase the image name +* Replace invalid chars sequences with `-` for tags + +### Latest tag + +`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=pep440,pattern=...`](#typepep440) +* [`type=match,pattern=...`](#typematch) + +For conditionally tagging with latest for a specific branch name, e.g. if your +default branch name is not `master`, use `type=raw` with a boolean expression: + +```yaml +tags: | + # set latest tag for master branch + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} +``` + +You can also use the [`{{is_default_branch}}` global expression](#is_default_branch) +to conditionally tag with latest for the default branch: + +```yaml +tags: | + # set latest tag for default branch + type=raw,value=latest,enable={{is_default_branch}} +``` + +### `priority` attribute + +`priority=` attribute is used to sort tags in the final list. The higher +the value, the higher the priority. The first tag in the list (higher priority) +will be used as the image version for generated OCI label and [`version` output](#outputs). +Each tags `type` attribute has a default priority: + +| Attribute | Default priority | +|------------|------------------| +| `schedule` | `1000` | +| `semver` | `900` | +| `pep440` | `900` | +| `match` | `800` | +| `edge` | `700` | +| `ref` | `600` | +| `raw` | `200` | +| `sha` | `100` | + +### Global expressions + +The following [Handlebars' template](https://handlebarsjs.com/guide/) expressions +for `prefix`, `suffix`, `value` and `enable` attributes of `tags` input are +available: + +```yaml +tags: | + # dynamically set the branch name as a prefix + type=sha,prefix={{branch}}- + # dynamically set the branch name and sha as a custom tag + type=raw,value=mytag-{{branch}}-{{sha}} +``` + +They can also be applied to `labels` and `annotations` inputs: + +```yaml +labels: | + org.opencontainers.image.created={{commit_date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}} +``` + +#### `{{branch}}` + +Returns the branch name that triggered the workflow run. Will be empty if not +a branch reference: + +| Event | Ref | Output | +|----------------|------------------------|-------------| +| `pull_request` | `refs/pull/2/merge` | | +| `push` | `refs/heads/master` | `master` | +| `push` | `refs/heads/my/branch` | `my-branch` | +| `push tag` | `refs/tags/v1.2.3` | | + +#### `{{tag}}` + +Returns the tag name that triggered the workflow run. Will be empty if not a +tag reference: + +| Event | Ref | Output | +|-----------------|-------------------------------|--------------------| +| `pull_request` | `refs/pull/2/merge` | | +| `push` | `refs/heads/master` | | +| `push` | `refs/heads/my/branch` | | +| `push tag` | `refs/tags/v1.2.3` | `v1.2.3` | + +#### `{{sha}}` + +Returns the short commit SHA that triggered the workflow run (e.g., `90dd603`). + +#### `{{base_ref}}` + +Returns the base ref or target branch of the pull request that triggered the +workflow run. Will be empty for a branch reference: + +| Event | Ref | Output | +|----------------|-------------------------------|--------------------| +| `pull_request` | `refs/pull/2/merge` | `master` | +| `push` | `refs/heads/master` | | +| `push` | `refs/heads/my/branch` | | +| `push tag`* | `refs/tags/v1.2.3` | `master` | + +> [!IMPORTANT] +> *`base_ref` is available in the push payload but doesn't always seem to +> return the expected branch when the push tag event occurs. It's also +> [not documented in GitHub docs](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push). +> We keep it for backward compatibility, but it's **not recommended relying on it**. +> More context in [#192](https://github.com/docker/metadata-action/pull/192#discussion_r854673012). + +#### `{{is_default_branch}}` + +Returns `true` if the branch that triggered the workflow run is the default +one, otherwise `false`. + +#### `{{is_not_default_branch}}` + +Returns `true` if the branch that triggered the workflow run is not the default +one, otherwise `false`. + +#### `{{date '' tz=''}}` + +Returns the current date rendered by its [moment format](https://momentjs.com/docs/#/displaying/format/). +Default `tz` is UTC. + +| Expression | Output example | +|----------------------------------------------|-----------------------------------------| +| `{{date 'YYYYMMDD'}}` | `20200110` | +| `{{date 'dddd, MMMM Do YYYY, h:mm:ss a'}}` | `Friday, January 10th 2020, 3:25:50 pm` | +| `{{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}` | `20200110-093000` | + +#### `{{commit_date '' tz=''}}` + +Returns the date when the current git commit is committed, rendered by its +[moment format](https://momentjs.com/docs/#/displaying/format/). It falls back +to the current date if the commit date is not available. + +Default `tz` is UTC. + +| Expression | Output example | +|-----------------------------------------------------|-----------------------------------------| +| `{{commit_date 'YYYYMMDD'}}` | `20200110` | +| `{{commit_date 'dddd, MMMM Do YYYY, h:mm:ss a'}}` | `Friday, January 10th 2020, 3:25:50 pm` | +| `{{commit_date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}` | `20200110-093000` | + +### Major version zero + +Major version zero (`0.y.z`) is for initial development and **may** change at +any time. This means the public API [**should not** be considered stable](https://semver.org/#spec-item-4). + +In this case, Docker tag `0` **should not** be generated if you're using [`type=semver`](#typesemver) +with `{{major}}` pattern. You can manage this behavior like this: + +```yaml +# refs/tags/v0.1.2 +tags: | + # output 0.1.2 + type=semver,pattern={{version}} + # output 0.1 + type=semver,pattern={{major}}.{{minor}} + # disabled if major zero + type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }} +``` + +### JSON output object + +The `json` output is a JSON object composed of the generated tags and labels so +that you can reuse them further in your workflow using the [`fromJSON` function](https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson): + +```yaml + - + name: Docker meta + uses: docker/metadata-action@v5 + id: meta + with: + images: name/app + - + name: Build and push + uses: docker/build-push-action@v6 + with: + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} + VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} + REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} +``` + +### Overwrite labels and annotations + +If some [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/master/annotations.md) +generated are not suitable as labels/annotations, you can overwrite them like +this: + +```yaml + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: name/app + labels: | + maintainer=CrazyMax + org.opencontainers.image.title=MyCustomTitle + org.opencontainers.image.description=Another description + org.opencontainers.image.vendor=MyCompany +``` + +### Annotations + +Since Buildx 0.12, it is possible to set annotations to your image through the +`--annotation` flag. + +With the [`build-push-action`](https://github.com/docker/build-push-action/), +you can set the `annotations` input with the value of the `annotations` output +of the `metadata-action`: + +```yaml + - + name: Docker meta + uses: docker/metadata-action@v5 + with: + images: name/app + - + name: Build and push + uses: docker/build-push-action@v6 + with: + tags: ${{ steps.meta.outputs.tags }} + annotations: ${{ steps.meta.outputs.annotations }} +``` + +The same can be done with the [`bake-action`](https://github.com/docker/bake-action/): + +```yaml + - + name: Docker meta + uses: docker/metadata-action@v5 + with: + images: name/app + - + name: Build + uses: docker/bake-action@v6 + with: + files: | + ./docker-bake.hcl + cwd://${{ steps.meta.outputs.bake-file-tags }} + cwd://${{ steps.meta.outputs.bake-file-annotations }} + targets: build +``` + +Note that annotations can be attached at many different levels within a manifest. +By default, the generated annotations will be attached to image manifests, +but different registries may expect annotations at different places; +a common practice is to read annotations at _image indexes_ if present, +which are often used by multi-arch builds to index platform-specific images. +If you want to specify level(s) for your annotations, you can use the +[`DOCKER_METADATA_ANNOTATIONS_LEVELS` environment variable](#environment-variables) +with a comma separated list of all levels the annotations should be attached to (defaults to `manifest`). +The following configuration demonstrates the ability to attach annotations to both image manifests and image indexes, +though your registry may only need annotations at the index level. (That is, `index` alone may be enough.) +Please consult the documentation of your registry. + +```yaml + - + name: Docker meta + uses: docker/metadata-action@v5 + with: + images: name/app + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + - + name: Build and push + uses: docker/build-push-action@v6 + with: + tags: ${{ steps.meta.outputs.tags }} + annotations: ${{ steps.meta.outputs.annotations }} +``` + +More information about annotations in the [BuildKit documentation](https://github.com/moby/buildkit/blob/master/docs/annotations.md). + +## Contributing + +Want to contribute? Awesome! You can find information about contributing to +this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md) + +# Training Comment +This is a minor change for the training manual. + \ No newline at end of file