Compare commits

..

No commits in common. "master" and "v5.7.0" have entirely different histories.

40 changed files with 10039 additions and 4124 deletions

3
.eslintignore Normal file
View file

@ -0,0 +1,3 @@
/dist/**
/coverage/**
/node_modules/**

24
.eslintrc.json Normal file
View file

@ -0,0 +1,24 @@
{
"env": {
"node": true,
"es6": true,
"jest": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest/recommended",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2023,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint",
"jest",
"prettier"
]
}

View file

@ -31,7 +31,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Docker meta
uses: ./
@ -43,10 +43,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -80,10 +80,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -116,10 +116,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -150,10 +150,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -181,10 +181,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -204,10 +204,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -225,10 +225,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -255,10 +255,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -278,17 +278,16 @@ jobs:
type=raw,value=gexp-tag-{{tag}}
type=raw,value=gexp-baseref-{{base_ref}}
type=raw,value=gexp-defbranch,enable={{is_default_branch}}
type=raw,value=gexp-notdefbranch,enable={{is_not_default_branch}}
json:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -320,10 +319,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver-opts: network=host
@ -345,7 +344,7 @@ jobs:
type=sha
-
name: Build and push to local registry
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: ./test
file: ./test/Dockerfile
@ -368,10 +367,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
-
@ -393,7 +392,7 @@ jobs:
type=sha
-
name: Build
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
files: |
./test/docker-bake.hcl
@ -413,10 +412,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -431,7 +430,7 @@ jobs:
sep-tags: ${{ matrix.sep }}
-
name: Tags
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
console.log(`${{ steps.meta.outputs.tags }}`);
@ -441,10 +440,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -462,7 +461,7 @@ jobs:
maintainer=Foo
-
name: Build
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: ./test
file: ./test/output.Dockerfile
@ -480,7 +479,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Docker meta
id: meta
@ -504,10 +503,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
-
@ -531,7 +530,7 @@ jobs:
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
-
name: Build
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
files: |
./test/docker-bake.hcl
@ -545,10 +544,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -571,10 +570,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: latest
-
@ -583,7 +582,7 @@ jobs:
uses: ./
-
name: Build
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
source: .
files: |
@ -604,10 +603,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.BUILDX_VERSION }}
driver: docker
@ -628,7 +627,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Dump context
uses: crazy-max/ghaction-dump-context@v2

View file

@ -1,45 +0,0 @@
name: codeql
on:
push:
branches:
- 'master'
- 'releases/v*'
pull_request:
permissions:
actions: read
contents: read
security-events: write
env:
NODE_VERSION: "24"
jobs:
analyze:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Enable corepack
run: |
corepack enable
yarn --version
-
name: Set up Node
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
-
name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: javascript-typescript
build-mode: none
-
name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:javascript-typescript"

View file

@ -1,17 +0,0 @@
name: pr-assign-author
permissions:
contents: read
on:
pull_request_target:
types:
- opened
- reopened
jobs:
run:
uses: crazy-max/.github/.github/workflows/pr-assign-author.yml@20ef82212dc54bab5749f5e05576ca6d3c8a5773 # v1.1.0
permissions:
contents: read
pull-requests: write

View file

@ -15,7 +15,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Publish
uses: actions/publish-immutable-action@v0.0.4

View file

@ -15,18 +15,14 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Test
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
source: .
targets: test
-
name: Upload coverage
uses: codecov/codecov-action@v5
with:
files: ./coverage/clover.xml
file: ./coverage/clover.xml
token: ${{ secrets.CODECOV_TOKEN }}

View file

@ -1,49 +0,0 @@
name: update-dist
on:
pull_request:
types:
- opened
- synchronize
jobs:
update-dist:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
-
name: GitHub auth token from GitHub App
id: docker-read-app
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.GHACTIONS_REPO_WRITE_APP_ID }}
private-key: ${{ secrets.GHACTIONS_REPO_WRITE_APP_PRIVATE_KEY }}
owner: docker
-
name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
token: ${{ steps.docker-read-app.outputs.token || github.token }}
-
name: Build
uses: docker/bake-action@v7
with:
source: .
targets: build
-
name: Commit and push dist
run: |
if [ -n "$(git status --porcelain -- dist)" ]; then
(
set -x
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add dist
git commit -m "chore: update generated content"
git push
)
else
echo "No changes in dist"
fi

View file

@ -15,15 +15,15 @@ jobs:
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.generate.outputs.matrix }}
targets: ${{ steps.generate.outputs.targets }}
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
-
name: Generate matrix
name: List targets
id: generate
uses: docker/bake-action/subaction/matrix@v7
uses: docker/bake-action/subaction/list-targets@v6
with:
target: validate
@ -34,10 +34,10 @@ jobs:
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.prepare.outputs.matrix) }}
target: ${{ fromJson(needs.prepare.outputs.targets) }}
steps:
-
name: Validate
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
targets: ${{ matrix.target }}

View file

@ -6,5 +6,6 @@
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid"
"arrowParens": "avoid",
"parser": "typescript"
}

File diff suppressed because one or more lines are too long

View file

@ -1,9 +1,3 @@
# https://yarnpkg.com/configuration/yarnrc
compressionLevel: mixed
enableGlobalCache: false
enableHardenedMode: true
logFilters:
- code: YN0013
level: discard
@ -11,7 +5,9 @@ logFilters:
level: discard
- code: YN0076
level: discard
- code: YN0086
level: discard
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"

118
README.md
View file

@ -44,7 +44,6 @@ ___
* [`{{sha}}`](#sha)
* [`{{base_ref}}`](#base_ref)
* [`{{is_default_branch}}`](#is_default_branch)
* [`{{is_not_default_branch}}`](#is_not_default_branch)
* [`{{date '<format>' tz='<timezone>'}}`](#date-format-tztimezone)
* [`{{commit_date '<format>' tz='<timezone>'}}`](#commit_date-format-tztimezone)
* [Major version zero](#major-version-zero)
@ -75,23 +74,27 @@ jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: name/app
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
@ -125,10 +128,13 @@ jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: |
name/app
@ -140,14 +146,15 @@ jobs:
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
@ -202,7 +209,7 @@ jobs:
-
name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: |
name/app
@ -214,7 +221,7 @@ jobs:
type=sha
-
name: Build
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
files: |
./docker-bake.hcl
@ -261,7 +268,7 @@ similar to the previous one:
```yaml
-
name: Build
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
files: |
./docker-bake.hcl
@ -276,7 +283,6 @@ similar to the previous one:
The following inputs can be used as `step.with` keys:
> [!NOTE]
> `List` type is a newline-delimited string
> ```yaml
> labels: |
@ -306,7 +312,6 @@ The following outputs are available:
|-------------------------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `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 |
@ -328,7 +333,7 @@ Alternatively, each output is also exported as an environment variable when `DOC
So it can be used with our [Docker Build Push action](https://github.com/docker/build-push-action/):
```yaml
- uses: docker/build-push-action@v7
- uses: docker/build-push-action@v6
with:
build-args: |
DOCKER_METADATA_OUTPUT_JSON
@ -456,7 +461,7 @@ tags: |
# handlebars
type=schedule,pattern={{date 'YYYYMMDD'}}
# handlebars with timezone
type=schedule,pattern={{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}
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).
@ -488,8 +493,6 @@ tags: |
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)
@ -505,21 +508,18 @@ with the following expressions:
* `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`* |
| 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}}` | `v2.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`* |
> [!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
@ -529,7 +529,7 @@ Extended attributes and default values:
```yaml
tags: |
type=semver,enable=true,priority=900,prefix=,suffix=,pattern=,value=,match=
type=semver,enable=true,priority=900,prefix=,suffix=,pattern=,value=
```
### `type=pep440`
@ -540,8 +540,6 @@ tags: |
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)
@ -557,22 +555,20 @@ with the following expressions:
* `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`* |
| Git tag | Pattern | 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` |
| `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
@ -720,7 +716,7 @@ increase this length for larger repositories by setting the
-
name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: |
name/app
@ -862,7 +858,6 @@ workflow run. Will be empty for a branch reference:
| `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).
@ -874,11 +869,6 @@ workflow run. Will be empty for a branch reference:
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 '<format>' tz='<timezone>'}}`
Returns the current date rendered by its [moment format](https://momentjs.com/docs/#/displaying/format/).
@ -931,13 +921,13 @@ that you can reuse them further in your workflow using the [`fromJSON` function]
```yaml
-
name: Docker meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
id: meta
with:
images: name/app
-
name: Build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
@ -957,7 +947,7 @@ this:
-
name: Docker meta
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: name/app
labels: |
@ -979,12 +969,12 @@ of the `metadata-action`:
```yaml
-
name: Docker meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: name/app
-
name: Build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
tags: ${{ steps.meta.outputs.tags }}
annotations: ${{ steps.meta.outputs.annotations }}
@ -995,12 +985,12 @@ The same can be done with the [`bake-action`](https://github.com/docker/bake-act
```yaml
-
name: Docker meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: name/app
-
name: Build
uses: docker/bake-action@v7
uses: docker/bake-action@v6
with:
files: |
./docker-bake.hcl
@ -1024,14 +1014,14 @@ Please consult the documentation of your registry.
```yaml
-
name: Docker meta
uses: docker/metadata-action@v6
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@v7
uses: docker/build-push-action@v6
with:
tags: ${{ steps.meta.outputs.tags }}
annotations: ${{ steps.meta.outputs.annotations }}

View file

@ -0,0 +1,223 @@
import {jest} from '@jest/globals';
export const context = {
repo: {
owner: 'docker',
repo: 'actions-toolkit'
},
ref: 'refs/heads/master',
runId: 123,
payload: {
after: '860c1904a1ce19322e91ac35af1ab07466440c37',
base_ref: null,
before: '5f3331d7f7044c18ca9f12c77d961c4d7cf3276a',
commits: [
{
author: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
committer: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
distinct: true,
id: '860c1904a1ce19322e91ac35af1ab07466440c37',
message: 'hello dev',
timestamp: '2022-04-19T11:27:24+02:00',
tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820',
url: 'https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37'
}
],
compare: 'https://github.com/docker/test-docker-action/compare/5f3331d7f704...860c1904a1ce',
created: false,
deleted: false,
forced: false,
head_commit: {
author: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
committer: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
distinct: true,
id: '860c1904a1ce19322e91ac35af1ab07466440c37',
message: 'hello dev',
timestamp: '2022-04-19T11:27:24+02:00',
tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820',
url: 'https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37'
},
organization: {
avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4',
description: 'Docker helps developers bring their ideas to life by conquering the complexity of app development.',
events_url: 'https://api.github.com/orgs/docker/events',
hooks_url: 'https://api.github.com/orgs/docker/hooks',
id: 5429470,
issues_url: 'https://api.github.com/orgs/docker/issues',
login: 'docker',
members_url: 'https://api.github.com/orgs/docker/members{/member}',
node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=',
public_members_url: 'https://api.github.com/orgs/docker/public_members{/member}',
repos_url: 'https://api.github.com/orgs/docker/repos',
url: 'https://api.github.com/orgs/docker'
},
pusher: {
email: 'github@crazymax.dev',
name: 'crazy-max'
},
ref: 'refs/heads/dev',
repository: {
allow_forking: true,
archive_url: 'https://api.github.com/repos/docker/test-docker-action/{archive_format}{/ref}',
archived: false,
assignees_url: 'https://api.github.com/repos/docker/test-docker-action/assignees{/user}',
blobs_url: 'https://api.github.com/repos/docker/test-docker-action/git/blobs{/sha}',
branches_url: 'https://api.github.com/repos/docker/test-docker-action/branches{/branch}',
clone_url: 'https://github.com/docker/test-docker-action.git',
collaborators_url: 'https://api.github.com/repos/docker/test-docker-action/collaborators{/collaborator}',
comments_url: 'https://api.github.com/repos/docker/test-docker-action/comments{/number}',
commits_url: 'https://api.github.com/repos/docker/test-docker-action/commits{/sha}',
compare_url: 'https://api.github.com/repos/docker/test-docker-action/compare/{base}...{head}',
contents_url: 'https://api.github.com/repos/docker/test-docker-action/contents/{+path}',
contributors_url: 'https://api.github.com/repos/docker/test-docker-action/contributors',
created_at: 1596792180,
default_branch: 'master',
deployments_url: 'https://api.github.com/repos/docker/test-docker-action/deployments',
description: 'Test "Docker" Actions',
disabled: false,
downloads_url: 'https://api.github.com/repos/docker/test-docker-action/downloads',
events_url: 'https://api.github.com/repos/docker/test-docker-action/events',
fork: false,
forks: 1,
forks_count: 1,
forks_url: 'https://api.github.com/repos/docker/test-docker-action/forks',
full_name: 'docker/test-docker-action',
git_commits_url: 'https://api.github.com/repos/docker/test-docker-action/git/commits{/sha}',
git_refs_url: 'https://api.github.com/repos/docker/test-docker-action/git/refs{/sha}',
git_tags_url: 'https://api.github.com/repos/docker/test-docker-action/git/tags{/sha}',
git_url: 'git://github.com/docker/test-docker-action.git',
has_downloads: true,
has_issues: true,
has_pages: false,
has_projects: true,
has_wiki: true,
homepage: '',
hooks_url: 'https://api.github.com/repos/docker/test-docker-action/hooks',
html_url: 'https://github.com/docker/test-docker-action',
id: 285789493,
is_template: false,
issue_comment_url: 'https://api.github.com/repos/docker/test-docker-action/issues/comments{/number}',
issue_events_url: 'https://api.github.com/repos/docker/test-docker-action/issues/events{/number}',
issues_url: 'https://api.github.com/repos/docker/test-docker-action/issues{/number}',
keys_url: 'https://api.github.com/repos/docker/test-docker-action/keys{/key_id}',
labels_url: 'https://api.github.com/repos/docker/test-docker-action/labels{/name}',
language: 'JavaScript',
languages_url: 'https://api.github.com/repos/docker/test-docker-action/languages',
license: {
key: 'mit',
name: 'MIT License',
node_id: 'MDc6TGljZW5zZTEz',
spdx_id: 'MIT',
url: 'https://api.github.com/licenses/mit'
},
master_branch: 'master',
merges_url: 'https://api.github.com/repos/docker/test-docker-action/merges',
milestones_url: 'https://api.github.com/repos/docker/test-docker-action/milestones{/number}',
mirror_url: null,
name: 'test-docker-action',
node_id: 'MDEwOlJlcG9zaXRvcnkyODU3ODk0OTM=',
notifications_url: 'https://api.github.com/repos/docker/test-docker-action/notifications{?since,all,participating}',
open_issues: 6,
open_issues_count: 6,
organization: 'docker',
owner: {
avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4',
email: 'info@docker.com',
events_url: 'https://api.github.com/users/docker/events{/privacy}',
followers_url: 'https://api.github.com/users/docker/followers',
following_url: 'https://api.github.com/users/docker/following{/other_user}',
gists_url: 'https://api.github.com/users/docker/gists{/gist_id}',
gravatar_id: '',
html_url: 'https://github.com/docker',
id: 5429470,
login: 'docker',
name: 'docker',
node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=',
organizations_url: 'https://api.github.com/users/docker/orgs',
received_events_url: 'https://api.github.com/users/docker/received_events',
repos_url: 'https://api.github.com/users/docker/repos',
site_admin: false,
starred_url: 'https://api.github.com/users/docker/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/docker/subscriptions',
type: 'Organization',
url: 'https://api.github.com/users/docker'
},
private: true,
pulls_url: 'https://api.github.com/repos/docker/test-docker-action/pulls{/number}',
pushed_at: 1650360446,
releases_url: 'https://api.github.com/repos/docker/test-docker-action/releases{/id}',
size: 796,
ssh_url: 'git@github.com:docker/test-docker-action.git',
stargazers: 0,
stargazers_count: 0,
stargazers_url: 'https://api.github.com/repos/docker/test-docker-action/stargazers',
statuses_url: 'https://api.github.com/repos/docker/test-docker-action/statuses/{sha}',
subscribers_url: 'https://api.github.com/repos/docker/test-docker-action/subscribers',
subscription_url: 'https://api.github.com/repos/docker/test-docker-action/subscription',
svn_url: 'https://github.com/docker/test-docker-action',
tags_url: 'https://api.github.com/repos/docker/test-docker-action/tags',
teams_url: 'https://api.github.com/repos/docker/test-docker-action/teams',
topics: [],
trees_url: 'https://api.github.com/repos/docker/test-docker-action/git/trees{/sha}',
updated_at: '2022-04-19T09:05:09Z',
url: 'https://github.com/docker/test-docker-action',
visibility: 'private',
watchers: 0,
watchers_count: 0
},
sender: {
avatar_url: 'https://avatars.githubusercontent.com/u/1951866?v=4',
events_url: 'https://api.github.com/users/crazy-max/events{/privacy}',
followers_url: 'https://api.github.com/users/crazy-max/followers',
following_url: 'https://api.github.com/users/crazy-max/following{/other_user}',
gists_url: 'https://api.github.com/users/crazy-max/gists{/gist_id}',
gravatar_id: '',
html_url: 'https://github.com/crazy-max',
id: 1951866,
login: 'crazy-max',
node_id: 'MDQ6VXNlcjE5NTE4NjY=',
organizations_url: 'https://api.github.com/users/crazy-max/orgs',
received_events_url: 'https://api.github.com/users/crazy-max/received_events',
repos_url: 'https://api.github.com/users/crazy-max/repos',
site_admin: false,
starred_url: 'https://api.github.com/users/crazy-max/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/crazy-max/subscriptions',
type: 'User',
url: 'https://api.github.com/users/crazy-max'
}
}
};
export const getOctokit = jest.fn(() => ({
rest: {
repos: {
getCommit: jest.fn(() =>
Promise.resolve({
data: {
commit: {
committer: {
date: '2024-11-13T13:42:28Z'
}
}
}
})
)
}
}
}));

View file

@ -1,11 +1,23 @@
import {beforeEach, describe, expect, test, it, vi} from 'vitest';
import {Git} from '@docker/actions-toolkit/lib/git.js';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
import {afterEach, beforeEach, describe, expect, test, it, jest} from '@jest/globals';
import * as dotenv from 'dotenv';
import * as fs from 'fs';
import * as path from 'path';
import {Context} from '@actions/github/lib/context';
import {Git} from '@docker/actions-toolkit/lib/git';
import {GitHub} from '@docker/actions-toolkit/lib/github';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
import * as context from '../src/context.js';
import {ContextSource, getContext, getInputs, Inputs} from '../src/context';
const toolkit = new Toolkit({githubToken: 'fake-github-token'});
beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(GitHub, 'context', 'get').mockImplementation((): Context => {
return new Context();
});
});
describe('getInputs', () => {
beforeEach(() => {
process.env = Object.keys(process.env).reduce((object, key) => {
@ -17,14 +29,14 @@ describe('getInputs', () => {
});
// prettier-ignore
const cases: [number, Map<string, string>, context.Inputs][] = [
test.each([
[
0,
new Map<string, string>([
['images', 'moby/buildkit\nghcr.io/moby/mbuildkit'],
]),
{
context: context.ContextSource.workflow,
context: ContextSource.workflow,
bakeTarget: 'docker-metadata-action',
flavor: [],
githubToken: '',
@ -35,7 +47,7 @@ describe('getInputs', () => {
sepTags: '\n',
sepAnnotations: '\n',
tags: [],
}
} as Inputs
],
[
1,
@ -47,7 +59,7 @@ describe('getInputs', () => {
['sep-annotations', ',']
]),
{
context: context.ContextSource.workflow,
context: ContextSource.workflow,
bakeTarget: 'metadata',
flavor: [],
githubToken: '',
@ -58,7 +70,7 @@ describe('getInputs', () => {
sepTags: ',',
sepAnnotations: ',',
tags: [],
}
} as Inputs
],
[
2,
@ -66,7 +78,7 @@ describe('getInputs', () => {
['images', 'moby/buildkit\n#comment\nghcr.io/moby/mbuildkit'],
]),
{
context: context.ContextSource.workflow,
context: ContextSource.workflow,
bakeTarget: 'docker-metadata-action',
flavor: [],
githubToken: '',
@ -77,100 +89,53 @@ describe('getInputs', () => {
sepTags: '\n',
sepAnnotations: '\n',
tags: [],
}
} as Inputs
],
[
3,
new Map<string, string>([
['labels', 'mylabel=foo#bar\n#comment\nanother=bar'],
]),
{
context: context.ContextSource.workflow,
bakeTarget: 'docker-metadata-action',
flavor: [],
githubToken: '',
images: [],
labels: ['mylabel=foo#bar', 'another=bar'],
annotations: [],
sepLabels: '\n',
sepTags: '\n',
sepAnnotations: '\n',
tags: [],
}
],
[
4,
new Map<string, string>([
['annotations', 'org.opencontainers.image.url=https://example.com/path#readme\n#comment\norg.opencontainers.image.source=https://github.com/docker/metadata-action'],
]),
{
context: context.ContextSource.workflow,
bakeTarget: 'docker-metadata-action',
flavor: [],
githubToken: '',
images: [],
labels: [],
annotations: [
'org.opencontainers.image.url=https://example.com/path#readme',
'org.opencontainers.image.source=https://github.com/docker/metadata-action'
],
sepLabels: '\n',
sepTags: '\n',
sepAnnotations: '\n',
tags: [],
}
],
[
5,
new Map<string, string>([
['tags', 'type=raw,value=foo#bar\n#comment'],
['flavor', 'prefix=v#1\n#comment'],
]),
{
context: context.ContextSource.workflow,
bakeTarget: 'docker-metadata-action',
flavor: ['prefix=v#1'],
githubToken: '',
images: [],
labels: [],
annotations: [],
sepLabels: '\n',
sepTags: '\n',
sepAnnotations: '\n',
tags: ['type=raw,value=foo#bar'],
}
],
];
test.each(cases)('[%d] given %o as inputs, returns %o', async (num: number, inputs: Map<string, string>, expected: context.Inputs) => {
inputs.forEach((value: string, name: string) => {
setInput(name, value);
});
const res = await context.getInputs();
expect(res).toEqual(expected);
});
])(
'[%d] given %p as inputs, returns %p',
async (num: number, inputs: Map<string, string>, expected: Inputs) => {
inputs.forEach((value: string, name: string) => {
setInput(name, value);
});
expect(await getInputs()).toEqual(expected);
}
);
});
describe('getContext', () => {
it('workflow', async () => {
const ctx = await context.getContext(context.ContextSource.workflow, toolkit);
expect(ctx.ref).toEqual('refs/heads/dev');
expect(ctx.sha).toEqual('5f3331d7f7044c18ca9f12c77d961c4d7cf3276a');
expect(ctx.commitDate).toEqual(new Date('2024-11-13T13:42:28.000Z'));
const originalEnv = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {
...originalEnv,
...dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures/event_create_branch.env')))
};
});
afterEach(() => {
process.env = originalEnv;
});
it('workflow', async () => {
const context = await getContext(ContextSource.workflow, toolkit);
expect(context.ref).toEqual('refs/heads/dev');
expect(context.sha).toEqual('5f3331d7f7044c18ca9f12c77d961c4d7cf3276a');
expect(context.commitDate).toEqual(new Date('2024-11-13T13:42:28.000Z'));
});
it('git', async () => {
vi.spyOn(Git, 'context').mockImplementation((): Promise<context.Context> => {
jest.spyOn(Git, 'context').mockImplementation((): Promise<Context> => {
return Promise.resolve({
ref: 'refs/heads/git-test',
sha: 'git-test-sha'
} as context.Context);
} as Context);
});
vi.spyOn(Git, 'commitDate').mockImplementation(async (): Promise<Date> => {
jest.spyOn(Git, 'commitDate').mockImplementation(async (): Promise<Date> => {
return new Date('2023-01-01T13:42:28.000Z');
});
const ctx = await context.getContext(context.ContextSource.git, toolkit);
expect(ctx.ref).toEqual('refs/heads/git-test');
expect(ctx.sha).toEqual('git-test-sha');
expect(ctx.commitDate).toEqual(new Date('2023-01-01T13:42:28.000Z'));
const context = await getContext(ContextSource.git, toolkit);
expect(context.ref).toEqual('refs/heads/git-test');
expect(context.sha).toEqual('git-test-sha');
expect(context.commitDate).toEqual(new Date('2023-01-01T13:42:28.000Z'));
});
});

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from 'vitest';
import {describe, expect, test} from '@jest/globals';
import {Flavor, Transform} from '../src/flavor.js';
import {Flavor, Transform} from '../src/flavor';
describe('transform', () => {
// prettier-ignore
@ -175,7 +175,7 @@ describe('transform', () => {
if (!invalid) {
console.error(err);
}
// eslint-disable-next-line vitest/no-conditional-expect
// eslint-disable-next-line jest/no-conditional-expect
expect(true).toBe(invalid);
}
});

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from 'vitest';
import {describe, expect, test} from '@jest/globals';
import {Transform, Image} from '../src/image.js';
import {Transform, Image} from '../src/image';
describe('transform', () => {
// prettier-ignore
@ -95,7 +95,7 @@ describe('transform', () => {
if (!invalid) {
console.error(err);
}
// eslint-disable-next-line vitest/no-conditional-expect
// eslint-disable-next-line jest/no-conditional-expect
expect(true).toBe(invalid);
}
});

View file

@ -1,65 +1,47 @@
import {beforeEach, describe, expect, test, vi} from 'vitest';
import {beforeEach, describe, expect, jest, test} from '@jest/globals';
import * as fs from 'fs';
import * as path from 'path';
import * as dotenv from 'dotenv';
import {GitHub} from '@docker/actions-toolkit/lib/github/github.js';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
import {GitHubRepo} from '@docker/actions-toolkit/lib/types/github/github.js';
import {Context} from '@actions/github/lib/context';
import {GitHub} from '@docker/actions-toolkit/lib/github';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
import {GitHubRepo} from '@docker/actions-toolkit/lib/types/github';
import {ContextSource, getContext, getInputs, Inputs} from '../src/context.js';
import type {Context as MetadataContext} from '../src/context.js';
import {Meta, Version} from '../src/meta.js';
import {ContextSource, getContext, getInputs, Inputs} from '../src/context';
import {Meta, Version} from '../src/meta';
import repoFixture from './fixtures/repo.json' with {type: 'json'};
import repoFixture from './fixtures/repo.json';
vi.spyOn(GitHub.prototype, 'repoData').mockImplementation((): Promise<GitHubRepo> => {
jest.spyOn(GitHub.prototype, 'repoData').mockImplementation((): Promise<GitHubRepo> => {
return <Promise<GitHubRepo>>(repoFixture as unknown);
});
vi.spyOn(global.Date.prototype, 'toISOString').mockImplementation(() => {
jest.spyOn(global.Date.prototype, 'toISOString').mockImplementation(() => {
return '2020-01-10T00:30:00.000Z';
});
vi.mock('moment-timezone', async () => {
const actual = await vi.importActual<unknown>('moment-timezone');
const actualModule = actual as {default?: (input?: string | Date) => unknown};
const momentTimezone = (typeof actual === 'function' ? actual : actualModule.default) as (input?: string | Date) => unknown;
return {
__esModule: true,
default: () => momentTimezone('2020-01-10T00:30:00.000Z')
};
jest.mock('moment-timezone', () => {
return () => (jest.requireActual('moment-timezone') as typeof import('moment-timezone'))('2020-01-10T00:30:00.000Z');
});
beforeEach(() => {
vi.clearAllMocks();
jest.clearAllMocks();
Object.keys(process.env).forEach(function (key) {
if (key !== 'GITHUB_TOKEN' && key.startsWith('GITHUB_')) {
delete process.env[key];
}
});
vi.spyOn(GitHub, 'context', 'get').mockImplementation((): MetadataContext => {
const repository = process.env.GITHUB_REPOSITORY || 'docker/repo';
const [owner, repo] = repository.includes('/') ? repository.split('/', 2) : ['docker', 'repo'];
const eventPath = process.env.GITHUB_EVENT_PATH;
const payload = eventPath && fs.existsSync(eventPath) ? JSON.parse(fs.readFileSync(eventPath, 'utf8')) : {};
jest.spyOn(GitHub, 'context', 'get').mockImplementation((): Context => {
//@ts-expect-error partial info
return {
payload,
eventName: process.env.GITHUB_EVENT_NAME || '',
sha: process.env.GITHUB_SHA || '',
ref: process.env.GITHUB_REF || '',
workflow: process.env.GITHUB_WORKFLOW || '',
action: process.env.GITHUB_ACTION || '',
actor: process.env.GITHUB_ACTOR || '',
job: process.env.GITHUB_JOB || '',
runAttempt: +(process.env.GITHUB_RUN_ATTEMPT || 1),
runNumber: +(process.env.GITHUB_RUN_NUMBER || 0),
runId: +(process.env.GITHUB_RUN_ID || 0),
apiUrl: process.env.GITHUB_API_URL || 'https://api.github.com',
serverUrl: process.env.GITHUB_SERVER_URL || 'https://github.com',
graphqlUrl: process.env.GITHUB_GRAPHQL_URL || 'https://api.github.com/graphql',
repo: {owner, repo}
} as MetadataContext;
...new Context(),
repo: {
owner: 'docker',
repo: 'repo'
}
};
});
});
@ -71,7 +53,7 @@ describe('isRawStatement', () => {
['{{ raw }}', true],
['{{ raw}}', true],
['{{raw}}', true],
])('given %o pattern', async (pattern: string, expected: boolean) => {
])('given %p pattern', async (pattern: string, expected: boolean) => {
expect(Meta.isRawStatement(pattern)).toEqual(expected);
});
});
@ -97,7 +79,7 @@ const tagsLabelsTest = async (name: string, envFile: string, inputs: Inputs, exV
describe('null', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'null01',
@ -151,12 +133,12 @@ describe('null', () => {
],
undefined
],
])('given %o with %o event', tagsLabelsTest);
])('given %p with %p event', tagsLabelsTest);
});
describe('push', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'push01',
@ -839,47 +821,13 @@ describe('push', () => {
"org.opencontainers.image.version=mytag-master"
],
undefined
],
[
'push22',
'event_push_dev.env',
{
images: ['org/app'],
tags: [
`type=edge,branch=master`,
`type=sha,format=long`,
`type=raw,value=notdefbranch,enable={{is_not_default_branch}}`
],
} as Inputs,
{
main: 'notdefbranch',
partial: [
'sha-860c1904a1ce19322e91ac35af1ab07466440c37'
],
latest: false
} as Version,
[
"org/app:notdefbranch",
"org/app:sha-860c1904a1ce19322e91ac35af1ab07466440c37"
],
[
"org.opencontainers.image.created=2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description=This your first repo!",
"org.opencontainers.image.licenses=MIT",
"org.opencontainers.image.revision=860c1904a1ce19322e91ac35af1ab07466440c37",
"org.opencontainers.image.source=https://github.com/octocat/Hello-World",
"org.opencontainers.image.title=Hello-World",
"org.opencontainers.image.url=https://github.com/octocat/Hello-World",
"org.opencontainers.image.version=notdefbranch"
],
undefined
]
])('given %o with %o event', tagsLabelsTest);
])('given %p with %p event', tagsLabelsTest);
});
describe('tag', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'tag01',
@ -1989,76 +1937,13 @@ describe('tag', () => {
"org.opencontainers.image.version=1.1.1"
],
undefined
],
[
'tag34',
'event_tag_p1-v1.0.0.env',
{
images: ['org/app'],
tags: [
`type=semver,pattern={{version}},"match=v(\\d.\\d.\\d)$"`,
]
} as Inputs,
{
main: '1.0.0',
partial: [],
latest: true
} as Version,
[
'org/app:1.0.0',
'org/app:latest'
],
[
"org.opencontainers.image.created=2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description=This your first repo!",
"org.opencontainers.image.licenses=MIT",
"org.opencontainers.image.revision=860c1904a1ce19322e91ac35af1ab07466440c37",
"org.opencontainers.image.source=https://github.com/octocat/Hello-World",
"org.opencontainers.image.title=Hello-World",
"org.opencontainers.image.url=https://github.com/octocat/Hello-World",
"org.opencontainers.image.version=1.0.0"
],
undefined
],
[
'push35',
'event_push_master.env',
{
images: ['user/app'],
tags: [
`type=semver,pattern={{version}},value=p1/v1.2.3,"match=v(\\d.\\d.\\d)$"`,
`type=pep440,pattern={{version}},value=p1/v1.2.3,"match=v(\\d.\\d.\\d)$"`,
`type=edge`
],
} as Inputs,
{
main: '1.2.3',
partial: ['edge'],
latest: true
} as Version,
[
'user/app:1.2.3',
'user/app:edge',
'user/app:latest'
],
[
"org.opencontainers.image.created=2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description=This your first repo!",
"org.opencontainers.image.licenses=MIT",
"org.opencontainers.image.revision=266574110acf203503badf966df2ea24b5d732d7",
"org.opencontainers.image.source=https://github.com/octocat/Hello-World",
"org.opencontainers.image.title=Hello-World",
"org.opencontainers.image.url=https://github.com/octocat/Hello-World",
"org.opencontainers.image.version=1.2.3"
],
undefined
]
])('given %o with %o event', tagsLabelsTest);
])('given %p with %p event', tagsLabelsTest);
});
describe('latest', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'latest01',
@ -2395,12 +2280,12 @@ describe('latest', () => {
],
undefined
]
])('given %o with %o event', tagsLabelsTest);
])('given %p with %p event', tagsLabelsTest);
});
describe('pr', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'pr01',
@ -2783,11 +2668,12 @@ describe('pr', () => {
],
undefined
],
])('given %o with %o event', tagsLabelsTest);
])('given %p with %p event', tagsLabelsTest);
});
describe('pr-head-sha', () => {
// prettier-ignore
// eslint-disable-next-line jest/expect-expect
test.each([
[
'pr01',
@ -3158,7 +3044,7 @@ describe('pr-head-sha', () => {
"org.opencontainers.image.version=src-2020-01-10T00-30-00Z",
]
],
])('given %o with %o event', async (name: string, envFile: string, inputs: Inputs, exVersion: Version, exTags: Array<string>, exLabelsAnnotations: Array<string>) => {
])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, exVersion: Version, exTags: Array<string>, exLabelsAnnotations: Array<string>) => {
process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile)));
process.env.DOCKER_METADATA_PR_HEAD_SHA = 'true';
@ -3182,7 +3068,7 @@ describe('pr-head-sha', () => {
describe('schedule', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'schedule01',
@ -3441,12 +3327,12 @@ describe('schedule', () => {
],
undefined
],
])('given %o with %o event', tagsLabelsTest);
])('given %p with %p event', tagsLabelsTest);
});
describe('release', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'release01',
@ -3543,12 +3429,12 @@ describe('release', () => {
],
undefined
]
])('given %o with %o event', tagsLabelsTest);
])('given %s with %p event', tagsLabelsTest);
});
describe('raw', () => {
// prettier-ignore
// eslint-disable-next-line vitest/expect-expect
// eslint-disable-next-line jest/expect-expect
test.each([
[
'raw01',
@ -3923,11 +3809,12 @@ describe('raw', () => {
],
undefined
],
])('given %o with %o event', tagsLabelsTest);
])('given %p wth %p event', tagsLabelsTest);
});
describe('json', () => {
// prettier-ignore
// eslint-disable-next-line jest/expect-expect
test.each([
[
'json01',
@ -3952,12 +3839,6 @@ describe('json', () => {
"user/app:custom",
"user/app:tags"
],
"tag-names": [
"dev",
"my",
"custom",
"tags"
],
"labels": {
"foo": "",
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
@ -3996,10 +3877,6 @@ describe('json', () => {
"user/app:dev",
"user/app:my",
],
"tag-names": [
"dev",
"my",
],
"labels": {
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description": "This your first repo!",
@ -4043,13 +3920,6 @@ describe('json', () => {
"user/app:tags",
"user/app:latest"
],
"tag-names": [
"release1",
"my",
"custom",
"tags",
"latest"
],
"labels": {
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description": "This your first repo!",
@ -4094,12 +3964,6 @@ describe('json', () => {
"user/app:custom",
"user/app:tags"
],
"tag-names": [
"20200110",
"my",
"custom",
"tags"
],
"labels": {
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description": "This your first repo!",
@ -4153,15 +4017,6 @@ describe('json', () => {
"ghcr.io/user/app:tags",
"ghcr.io/user/app:latest"
],
"tag-names": [
"1.1.1",
"1.1",
"1",
"my",
"custom",
"tags",
"latest",
],
"labels": {
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description": "This your first repo!",
@ -4204,11 +4059,6 @@ describe('json', () => {
"ghcr.io/user/app:custom",
"ghcr.io/user/app:tags"
],
"tag-names": [
"my",
"custom",
"tags",
],
"labels": {
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
"org.opencontainers.image.description": "This your first repo!",
@ -4249,10 +4099,6 @@ describe('json', () => {
"org/app:v1.1.1",
"org/app:latest"
],
"tag-names": [
"v1.1.1",
"latest"
],
"labels": {
"maintainer": "CrazyMax",
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
@ -4277,7 +4123,7 @@ describe('json', () => {
]
}
]
])('given %o with %o event', async (name: string, envFile: string, inputs: Inputs, exJSON: unknown) => {
])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, exJSON: unknown) => {
process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile)));
const toolkit = new Toolkit();
@ -4291,6 +4137,7 @@ describe('json', () => {
describe('bakeFile', () => {
// prettier-ignore
// eslint-disable-next-line jest/expect-expect
test.each([
[
'bakeFile01',
@ -4792,7 +4639,7 @@ describe('bakeFile', () => {
}
}
]
])('given %o with %o event', async (name: string, envFile: string, inputs: Inputs, exBakeTags: unknown, exBakeLabels: unknown, exBakeAnnotations: unknown) => {
])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, exBakeTags: unknown, exBakeLabels: unknown, exBakeAnnotations: unknown) => {
process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile)));
const toolkit = new Toolkit();
@ -4812,6 +4659,7 @@ describe('bakeFile', () => {
describe('bakeFileTagsLabels', () => {
// prettier-ignore
// eslint-disable-next-line jest/expect-expect
test.each([
[
'bakeFileTagsLabels01',
@ -4855,7 +4703,7 @@ describe('bakeFileTagsLabels', () => {
}
}
]
])('given %o with %o event', async (name: string, envFile: string, inputs: Inputs, exBakeDefinition: unknown) => {
])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, exBakeDefinition: unknown) => {
process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile)));
const toolkit = new Toolkit();
@ -4869,6 +4717,7 @@ describe('bakeFileTagsLabels', () => {
describe('sepTags', () => {
// prettier-ignore
// eslint-disable-next-line jest/expect-expect
test.each([
[
'sepTags01',
@ -4900,11 +4749,14 @@ describe('sepTags', () => {
} as Inputs,
"user/app:dev,user/app:my,user/app:custom,user/app:tags"
]
])('given %o with %o event', async (name: string, envFile: string, inputs: Inputs, expTags: string) => {
])('given %p with %p event', async (name: string, envFile: string, inputs: Inputs, expTags: string) => {
process.env = dotenv.parse(fs.readFileSync(path.join(__dirname, 'fixtures', envFile)));
const toolkit = new Toolkit();
const repo = await toolkit.github.repoData();
const meta = new Meta({...getInputs(), ...inputs}, await getContext(ContextSource.workflow, toolkit), repo);
expect(meta.getTags().join(inputs.sepTags)).toEqual(expTags);

View file

@ -1,252 +0,0 @@
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import {vi} from 'vitest';
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-metadata-action-'));
const githubPayload = {
after: '860c1904a1ce19322e91ac35af1ab07466440c37',
base_ref: null,
before: '5f3331d7f7044c18ca9f12c77d961c4d7cf3276a',
commits: [
{
author: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
committer: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
distinct: true,
id: '5f3331d7f7044c18ca9f12c77d961c4d7cf3276a',
message: 'hello dev',
timestamp: '2024-11-13T13:42:28Z',
tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820',
url: 'https://github.com/docker/test-docker-action/commit/5f3331d7f7044c18ca9f12c77d961c4d7cf3276a'
}
],
compare: 'https://github.com/docker/test-docker-action/compare/5f3331d7f704...860c1904a1ce',
created: false,
deleted: false,
forced: false,
head_commit: {
author: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
committer: {
email: 'crazy-max@users.noreply.github.com',
name: 'CrazyMax',
username: 'crazy-max'
},
distinct: true,
id: '5f3331d7f7044c18ca9f12c77d961c4d7cf3276a',
message: 'hello dev',
timestamp: '2024-11-13T13:42:28Z',
tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820',
url: 'https://github.com/docker/test-docker-action/commit/5f3331d7f7044c18ca9f12c77d961c4d7cf3276a'
},
organization: {
avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4',
description: 'Docker helps developers bring their ideas to life by conquering the complexity of app development.',
events_url: 'https://api.github.com/orgs/docker/events',
hooks_url: 'https://api.github.com/orgs/docker/hooks',
id: 5429470,
issues_url: 'https://api.github.com/orgs/docker/issues',
login: 'docker',
members_url: 'https://api.github.com/orgs/docker/members{/member}',
node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=',
public_members_url: 'https://api.github.com/orgs/docker/public_members{/member}',
repos_url: 'https://api.github.com/orgs/docker/repos',
url: 'https://api.github.com/orgs/docker'
},
pusher: {
email: 'github@crazymax.dev',
name: 'crazy-max'
},
ref: 'refs/heads/dev',
repository: {
allow_forking: true,
archive_url: 'https://api.github.com/repos/docker/test-docker-action/{archive_format}{/ref}',
archived: false,
assignees_url: 'https://api.github.com/repos/docker/test-docker-action/assignees{/user}',
blobs_url: 'https://api.github.com/repos/docker/test-docker-action/git/blobs{/sha}',
branches_url: 'https://api.github.com/repos/docker/test-docker-action/branches{/branch}',
clone_url: 'https://github.com/docker/test-docker-action.git',
collaborators_url: 'https://api.github.com/repos/docker/test-docker-action/collaborators{/collaborator}',
comments_url: 'https://api.github.com/repos/docker/test-docker-action/comments{/number}',
commits_url: 'https://api.github.com/repos/docker/test-docker-action/commits{/sha}',
compare_url: 'https://api.github.com/repos/docker/test-docker-action/compare/{base}...{head}',
contents_url: 'https://api.github.com/repos/docker/test-docker-action/contents/{+path}',
contributors_url: 'https://api.github.com/repos/docker/test-docker-action/contributors',
created_at: 1596792180,
default_branch: 'master',
deployments_url: 'https://api.github.com/repos/docker/test-docker-action/deployments',
description: 'Test "Docker" Actions',
disabled: false,
downloads_url: 'https://api.github.com/repos/docker/test-docker-action/downloads',
events_url: 'https://api.github.com/repos/docker/test-docker-action/events',
fork: false,
forks: 1,
forks_count: 1,
forks_url: 'https://api.github.com/repos/docker/test-docker-action/forks',
full_name: 'docker/test-docker-action',
git_commits_url: 'https://api.github.com/repos/docker/test-docker-action/git/commits{/sha}',
git_refs_url: 'https://api.github.com/repos/docker/test-docker-action/git/refs{/sha}',
git_tags_url: 'https://api.github.com/repos/docker/test-docker-action/git/tags{/sha}',
git_url: 'git://github.com/docker/test-docker-action.git',
has_downloads: true,
has_issues: true,
has_pages: false,
has_projects: true,
has_wiki: true,
homepage: '',
hooks_url: 'https://api.github.com/repos/docker/test-docker-action/hooks',
html_url: 'https://github.com/docker/test-docker-action',
id: 285789493,
is_template: false,
issue_comment_url: 'https://api.github.com/repos/docker/test-docker-action/issues/comments{/number}',
issue_events_url: 'https://api.github.com/repos/docker/test-docker-action/issues/events{/number}',
issues_url: 'https://api.github.com/repos/docker/test-docker-action/issues{/number}',
keys_url: 'https://api.github.com/repos/docker/test-docker-action/keys{/key_id}',
labels_url: 'https://api.github.com/repos/docker/test-docker-action/labels{/name}',
language: 'JavaScript',
languages_url: 'https://api.github.com/repos/docker/test-docker-action/languages',
license: {
key: 'mit',
name: 'MIT License',
node_id: 'MDc6TGljZW5zZTEz',
spdx_id: 'MIT',
url: 'https://api.github.com/licenses/mit'
},
master_branch: 'master',
merges_url: 'https://api.github.com/repos/docker/test-docker-action/merges',
milestones_url: 'https://api.github.com/repos/docker/test-docker-action/milestones{/number}',
mirror_url: null,
name: 'test-docker-action',
node_id: 'MDEwOlJlcG9zaXRvcnkyODU3ODk0OTM=',
notifications_url: 'https://api.github.com/repos/docker/test-docker-action/notifications{?since,all,participating}',
open_issues: 6,
open_issues_count: 6,
organization: 'docker',
owner: {
avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4',
email: 'info@docker.com',
events_url: 'https://api.github.com/users/docker/events{/privacy}',
followers_url: 'https://api.github.com/users/docker/followers',
following_url: 'https://api.github.com/users/docker/following{/other_user}',
gists_url: 'https://api.github.com/users/docker/gists{/gist_id}',
gravatar_id: '',
html_url: 'https://github.com/docker',
id: 5429470,
login: 'docker',
name: 'docker',
node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=',
organizations_url: 'https://api.github.com/users/docker/orgs',
received_events_url: 'https://api.github.com/users/docker/received_events',
repos_url: 'https://api.github.com/users/docker/repos',
site_admin: false,
starred_url: 'https://api.github.com/users/docker/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/docker/subscriptions',
type: 'Organization',
url: 'https://api.github.com/users/docker'
},
private: true,
pulls_url: 'https://api.github.com/repos/docker/test-docker-action/pulls{/number}',
pushed_at: 1650360446,
releases_url: 'https://api.github.com/repos/docker/test-docker-action/releases{/id}',
size: 796,
ssh_url: 'git@github.com:docker/test-docker-action.git',
stargazers: 0,
stargazers_count: 0,
stargazers_url: 'https://api.github.com/repos/docker/test-docker-action/stargazers',
statuses_url: 'https://api.github.com/repos/docker/test-docker-action/statuses/{sha}',
subscribers_url: 'https://api.github.com/repos/docker/test-docker-action/subscribers',
subscription_url: 'https://api.github.com/repos/docker/test-docker-action/subscription',
svn_url: 'https://github.com/docker/test-docker-action',
tags_url: 'https://api.github.com/repos/docker/test-docker-action/tags',
teams_url: 'https://api.github.com/repos/docker/test-docker-action/teams',
topics: [],
trees_url: 'https://api.github.com/repos/docker/test-docker-action/git/trees{/sha}',
updated_at: '2022-04-19T09:05:09Z',
url: 'https://github.com/docker/test-docker-action',
visibility: 'private',
watchers: 0,
watchers_count: 0
},
sender: {
avatar_url: 'https://avatars.githubusercontent.com/u/1951866?v=4',
events_url: 'https://api.github.com/users/crazy-max/events{/privacy}',
followers_url: 'https://api.github.com/users/crazy-max/followers',
following_url: 'https://api.github.com/users/crazy-max/following{/other_user}',
gists_url: 'https://api.github.com/users/crazy-max/gists{/gist_id}',
gravatar_id: '',
html_url: 'https://github.com/crazy-max',
id: 1951866,
login: 'crazy-max',
node_id: 'MDQ6VXNlcjE5NTE4NjY=',
organizations_url: 'https://api.github.com/users/crazy-max/orgs',
received_events_url: 'https://api.github.com/users/crazy-max/received_events',
repos_url: 'https://api.github.com/users/crazy-max/repos',
site_admin: false,
starred_url: 'https://api.github.com/users/crazy-max/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/crazy-max/subscriptions',
type: 'User',
url: 'https://api.github.com/users/crazy-max'
}
};
const githubEventPath = path.join(tmpDir, 'github-event.json');
fs.writeFileSync(githubEventPath, JSON.stringify(githubPayload));
process.env = Object.assign({}, process.env, {
TEMP: tmpDir,
GITHUB_REPOSITORY: 'docker/metadata-action',
GITHUB_REF: 'refs/heads/dev',
GITHUB_RUN_ID: '2188748038',
GITHUB_RUN_ATTEMPT: '1',
GITHUB_RUN_NUMBER: '15',
GITHUB_SHA: '5f3331d7f7044c18ca9f12c77d961c4d7cf3276a',
GITHUB_EVENT_PATH: githubEventPath,
RUNNER_TEMP: path.join(tmpDir, 'runner-temp'),
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache')
});
const getCommitMock = vi.hoisted(() =>
vi.fn(async () => ({
data: {
commit: {
committer: {
date: '2024-11-13T13:42:28Z'
}
}
}
}))
);
const getOctokitMock = vi.hoisted(() =>
vi.fn(() => ({
rest: {
repos: {
getCommit: getCommitMock
}
}
}))
);
vi.mock('@actions/github', async importOriginal => {
const actual = await importOriginal<typeof import('@actions/github')>();
return {
...actual,
context: {
...actual.context,
payload: githubPayload
},
getOctokit: getOctokitMock
};
});

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from 'vitest';
import {describe, expect, test} from '@jest/globals';
import {Transform, Parse, Tag, Type, RefEvent, ShaFormat, DefaultPriorities} from '../src/tag.js';
import {Transform, Parse, Tag, Type, RefEvent, ShaFormat, DefaultPriorities} from '../src/tag';
describe('transform', () => {
// prettier-ignore
@ -32,8 +32,7 @@ describe('transform', () => {
"priority": DefaultPriorities[Type.Semver],
"enable": "true",
"pattern": "{{version}}",
"value": "",
"match": ""
"value": ""
}
},
{
@ -107,7 +106,7 @@ describe('transform', () => {
if (!invalid) {
console.error(err);
}
// eslint-disable-next-line vitest/no-conditional-expect
// eslint-disable-next-line jest/no-conditional-expect
expect(true).toBe(invalid);
}
});
@ -148,8 +147,7 @@ describe('parse', () => {
"priority": DefaultPriorities[Type.Semver],
"enable": "true",
"pattern": "{{version}}",
"value": "",
"match": ""
"value": ""
}
} as Tag,
false
@ -162,8 +160,7 @@ describe('parse', () => {
"priority": "1",
"enable": "true",
"pattern": "{{version}}",
"value": "",
"match": ""
"value": ""
}
} as Tag,
false
@ -176,22 +173,7 @@ describe('parse', () => {
"priority": "1",
"enable": "true",
"pattern": "{{version}}",
"value": "v1.0.0",
"match": ""
}
} as Tag,
false
],
[
`type=semver,priority=1,enable=true,pattern={{version}},value=p1/v1.0.0,"match=v(\\d.\\d.\\d)$"`,
{
type: Type.Semver,
attrs: {
"priority": "1",
"enable": "true",
"pattern": "{{version}}",
"value": "p1/v1.0.0",
"match": "v(\\d.\\d.\\d)$"
"value": "v1.0.0"
}
} as Tag,
false
@ -461,7 +443,7 @@ describe('parse', () => {
if (!invalid) {
console.error(err);
}
// eslint-disable-next-line vitest/no-conditional-expect
// eslint-disable-next-line jest/no-conditional-expect
expect(true).toBe(invalid);
}
});

View file

@ -48,8 +48,6 @@ outputs:
description: 'Generated Docker image version'
tags:
description: 'Generated Docker tags'
tag-names:
description: 'Generated Docker tag names without image base name'
labels:
description: 'Generated Docker labels'
annotations:
@ -66,5 +64,5 @@ outputs:
description: 'Bake definition file with tags and labels'
runs:
using: 'node24'
using: 'node20'
main: 'dist/index.js'

View file

@ -1,13 +1,12 @@
# syntax=docker/dockerfile:1
ARG NODE_VERSION=24
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache cpio findutils git rsync
RUN apk add --no-cache cpio findutils git
WORKDIR /src
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache <<EOT
set -e
corepack enable
yarn --version
yarn config set --home enableTelemetry 0
@ -35,27 +34,18 @@ RUN --mount=type=bind,target=.,rw <<EOT
EOT
FROM deps AS build
RUN --mount=target=/context \
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules <<EOT
set -e
rsync -a /context/. .
rm -rf dist
yarn run build
mkdir /out
cp -r dist /out
EOT
--mount=type=cache,target=/src/node_modules \
yarn run build && mkdir /out && cp -Rf dist /out/
FROM scratch AS build-update
COPY --from=build /out /
FROM build AS build-validate
RUN --mount=target=/context \
--mount=target=.,type=tmpfs <<EOT
RUN --mount=type=bind,target=.,rw <<EOT
set -e
rsync -a /context/. .
git add -A
rm -rf dist
cp -rf /out/* .
if [ -n "$(git status --porcelain -- dist)" ]; then
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
@ -68,7 +58,8 @@ FROM deps AS format
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run format && mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
yarn run format \
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
FROM scratch AS format-update
COPY --from=format /out /
@ -83,7 +74,7 @@ FROM deps AS test
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run test --coverage --coverage.reportsDirectory=/tmp/coverage
yarn run test --coverage --coverageDirectory=/tmp/coverage
FROM scratch AS test-coverage
COPY --from=test /tmp/coverage /

299
dist/606.index.js generated vendored
View file

@ -1,299 +0,0 @@
export const id = 606;
export const ids = [606];
export const modules = {
/***/ 606:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ pMap)
/* harmony export */ });
/* unused harmony exports pMapIterable, pMapSkip */
async function pMap(
iterable,
mapper,
{
concurrency = Number.POSITIVE_INFINITY,
stopOnError = true,
signal,
} = {},
) {
return new Promise((resolve_, reject_) => {
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
}
if (typeof mapper !== 'function') {
throw new TypeError('Mapper function is required');
}
if (!((Number.isSafeInteger(concurrency) && concurrency >= 1) || concurrency === Number.POSITIVE_INFINITY)) {
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
}
const result = [];
const errors = [];
const skippedIndexesMap = new Map();
let isRejected = false;
let isResolved = false;
let isIterableDone = false;
let resolvingCount = 0;
let currentIndex = 0;
const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
const signalListener = () => {
reject(signal.reason);
};
const cleanup = () => {
signal?.removeEventListener('abort', signalListener);
};
const resolve = value => {
resolve_(value);
cleanup();
};
const reject = reason => {
isRejected = true;
isResolved = true;
reject_(reason);
cleanup();
};
if (signal) {
if (signal.aborted) {
reject(signal.reason);
}
signal.addEventListener('abort', signalListener, {once: true});
}
const next = async () => {
if (isResolved) {
return;
}
const nextItem = await iterator.next();
const index = currentIndex;
currentIndex++;
// Note: `iterator.next()` can be called many times in parallel.
// This can cause multiple calls to this `next()` function to
// receive a `nextItem` with `done === true`.
// The shutdown logic that rejects/resolves must be protected
// so it runs only one time as the `skippedIndex` logic is
// non-idempotent.
if (nextItem.done) {
isIterableDone = true;
if (resolvingCount === 0 && !isResolved) {
if (!stopOnError && errors.length > 0) {
reject(new AggregateError(errors)); // eslint-disable-line unicorn/error-message
return;
}
isResolved = true;
if (skippedIndexesMap.size === 0) {
resolve(result);
return;
}
const pureResult = [];
// Support multiple `pMapSkip`'s.
for (const [index, value] of result.entries()) {
if (skippedIndexesMap.get(index) === pMapSkip) {
continue;
}
pureResult.push(value);
}
resolve(pureResult);
}
return;
}
resolvingCount++;
// Intentionally detached
(async () => {
try {
const element = await nextItem.value;
if (isResolved) {
return;
}
const value = await mapper(element, index);
// Use Map to stage the index of the element.
if (value === pMapSkip) {
skippedIndexesMap.set(index, value);
}
result[index] = value;
resolvingCount--;
await next();
} catch (error) {
if (stopOnError) {
reject(error);
} else {
errors.push(error);
resolvingCount--;
// In that case we can't really continue regardless of `stopOnError` state
// since an iterable is likely to continue throwing after it throws once.
// If we continue calling `next()` indefinitely we will likely end up
// in an infinite loop of failed iteration.
try {
await next();
} catch (error) {
reject(error);
}
}
}
})();
};
// Create the concurrent runners in a detached (non-awaited)
// promise. We need this so we can await the `next()` calls
// to stop creating runners before hitting the concurrency limit
// if the iterable has already been marked as done.
// NOTE: We *must* do this for async iterators otherwise we'll spin up
// infinite `next()` calls by default and never start the event loop.
(async () => {
for (let index = 0; index < concurrency; index++) {
try {
// eslint-disable-next-line no-await-in-loop
await next();
} catch (error) {
reject(error);
break;
}
if (isIterableDone || isRejected) {
break;
}
}
})();
});
}
function pMapIterable(
iterable,
mapper,
{
concurrency = Number.POSITIVE_INFINITY,
backpressure = concurrency,
} = {},
) {
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
}
if (typeof mapper !== 'function') {
throw new TypeError('Mapper function is required');
}
if (!((Number.isSafeInteger(concurrency) && concurrency >= 1) || concurrency === Number.POSITIVE_INFINITY)) {
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
}
if (!((Number.isSafeInteger(backpressure) && backpressure >= concurrency) || backpressure === Number.POSITIVE_INFINITY)) {
throw new TypeError(`Expected \`backpressure\` to be an integer from \`concurrency\` (${concurrency}) and up or \`Infinity\`, got \`${backpressure}\` (${typeof backpressure})`);
}
return {
async * [Symbol.asyncIterator]() {
const iterator = iterable[Symbol.asyncIterator] === undefined ? iterable[Symbol.iterator]() : iterable[Symbol.asyncIterator]();
const promises = [];
let runningMappersCount = 0;
let isDone = false;
let index = 0;
function trySpawn() {
if (isDone || !(runningMappersCount < concurrency && promises.length < backpressure)) {
return;
}
const promise = (async () => {
const {done, value} = await iterator.next();
if (done) {
return {done: true};
}
runningMappersCount++;
// Spawn if still below concurrency and backpressure limit
trySpawn();
try {
const returnValue = await mapper(await value, index++);
runningMappersCount--;
if (returnValue === pMapSkip) {
const index = promises.indexOf(promise);
if (index > 0) {
promises.splice(index, 1);
}
}
// Spawn if still below backpressure limit and just dropped below concurrency limit
trySpawn();
return {done: false, value: returnValue};
} catch (error) {
isDone = true;
return {error};
}
})();
promises.push(promise);
}
trySpawn();
while (promises.length > 0) {
const {error, done, value} = await promises[0]; // eslint-disable-line no-await-in-loop
promises.shift();
if (error) {
throw error;
}
if (done) {
return;
}
// Spawn if just dropped below backpressure limit and below the concurrency limit
trySpawn();
if (value === pMapSkip) {
continue;
}
yield value;
}
},
};
}
const pMapSkip = Symbol('skip');
/***/ })
};
//# sourceMappingURL=606.index.js.map

1
dist/606.index.js.map generated vendored

File diff suppressed because one or more lines are too long

150
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

4045
dist/licenses.txt generated vendored

File diff suppressed because it is too large Load diff

3
dist/package.json generated vendored
View file

@ -1,3 +0,0 @@
{
"type": "module"
}

1
dist/sourcemap-register.cjs generated vendored

File diff suppressed because one or more lines are too long

1
dist/sourcemap-register.js generated vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,52 +0,0 @@
import {defineConfig} from 'eslint/config';
import js from '@eslint/js';
import tseslint from '@typescript-eslint/eslint-plugin';
import vitest from '@vitest/eslint-plugin';
import globals from 'globals';
import eslintConfigPrettier from 'eslint-config-prettier/flat';
import eslintPluginPrettier from 'eslint-plugin-prettier';
export default defineConfig([
{
ignores: ['.yarn/**/*', 'coverage/**/*', 'dist/**/*']
},
js.configs.recommended,
...tseslint.configs['flat/recommended'],
eslintConfigPrettier,
{
languageOptions: {
globals: {
...globals.node
}
}
},
{
files: ['__tests__/**'],
...vitest.configs.recommended,
languageOptions: {
globals: {
...globals.node,
...vitest.environments.env.globals
}
},
rules: {
...vitest.configs.recommended.rules,
'vitest/no-conditional-expect': 'error',
'vitest/no-disabled-tests': 0
}
},
{
plugins: {
prettier: eslintPluginPrettier
},
rules: {
'prettier/prettier': 'error',
'@typescript-eslint/no-require-imports': [
'error',
{
allowAsImport: true
}
]
}
}
]);

31
jest.config.ts Normal file
View file

@ -0,0 +1,31 @@
import fs from 'fs';
import os from 'os';
import path from 'path';
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-metadata-action-'));
process.env = Object.assign({}, process.env, {
TEMP: tmpDir,
GITHUB_REPOSITORY: 'docker/metadata-action',
RUNNER_TEMP: path.join(tmpDir, 'runner-temp'),
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache')
}) as {
[key: string]: string;
};
module.exports = {
clearMocks: true,
testEnvironment: 'node',
moduleFileExtensions: ['js', 'ts'],
setupFiles: ['dotenv/config'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
moduleNameMapper: {
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
},
collectCoverageFrom: ['src/**/{!(main.ts),}.ts'],
coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__mocks__/', '__tests__/'],
verbose: true
};

View file

@ -1,13 +1,16 @@
{
"name": "docker-metadata-action",
"description": "GitHub Action to extract metadata (tags, labels) for Docker",
"type": "module",
"main": "src/main.ts",
"scripts": {
"build": "ncc build --source-map --minify --license licenses.txt",
"lint": "eslint --max-warnings=0 .",
"format": "eslint --fix .",
"test": "vitest run"
"lint": "yarn run prettier && yarn run eslint",
"format": "yarn run prettier:fix && yarn run eslint:fix",
"eslint": "eslint --max-warnings=0 .",
"eslint:fix": "eslint --fix .",
"prettier": "prettier --check \"./**/*.ts\"",
"prettier:fix": "prettier --write \"./**/*.ts\"",
"test": "jest"
},
"repository": {
"type": "git",
@ -22,34 +25,34 @@
],
"author": "Docker Inc.",
"license": "Apache-2.0",
"packageManager": "yarn@4.9.2",
"packageManager": "yarn@3.6.3",
"dependencies": {
"@actions/core": "^3.0.0",
"@actions/github": "^9.0.0",
"@docker/actions-toolkit": "^0.79.0",
"@actions/core": "^1.11.1",
"@actions/github": "^6.0.0",
"@docker/actions-toolkit": "^0.56.0",
"@renovate/pep440": "^1.0.0",
"csv-parse": "^6.1.0",
"csv-parse": "^5.6.0",
"handlebars": "^4.7.8",
"moment": "^2.30.1",
"moment-timezone": "^0.6.1",
"semver": "^7.7.4"
"moment-timezone": "^0.5.47",
"semver": "^7.7.1"
},
"devDependencies": {
"@eslint/js": "^9.39.3",
"@types/node": "^24.11.0",
"@types/semver": "^7.7.1",
"@typescript-eslint/eslint-plugin": "^8.56.1",
"@typescript-eslint/parser": "^8.56.1",
"@vercel/ncc": "^0.38.4",
"@vitest/coverage-v8": "^4.0.18",
"@vitest/eslint-plugin": "^1.6.9",
"dotenv": "^17.3.1",
"eslint": "^9.39.3",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",
"globals": "^17.3.0",
"prettier": "^3.8.1",
"typescript": "^5.9.3",
"vitest": "^4.0.18"
"@types/csv-parse": "^1.2.2",
"@types/node": "^20.12.12",
"@types/semver": "^7.5.8",
"@typescript-eslint/eslint-plugin": "^7.9.0",
"@typescript-eslint/parser": "^7.9.0",
"@vercel/ncc": "^0.38.1",
"dotenv": "^16.4.5",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jest": "^28.5.0",
"eslint-plugin-prettier": "^5.1.3",
"jest": "^29.7.0",
"prettier": "^3.2.5",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}

View file

@ -1,11 +1,9 @@
import * as core from '@actions/core';
import {Util} from '@docker/actions-toolkit/lib/util.js';
import {Git} from '@docker/actions-toolkit/lib/git.js';
import {GitHub} from '@docker/actions-toolkit/lib/github/github.js';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
type GithubContext = typeof GitHub.context;
import {Context as GithubContext} from '@actions/github/lib/context';
import {Util} from '@docker/actions-toolkit/lib/util';
import {Git} from '@docker/actions-toolkit/lib/git';
import {GitHub} from '@docker/actions-toolkit/lib/github';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
export interface Context extends GithubContext {
commitDate: Date;
@ -28,11 +26,11 @@ export interface Inputs {
export function getInputs(): Inputs {
return {
context: (core.getInput('context') || ContextSource.workflow) as ContextSource,
images: Util.getInputList('images', {ignoreComma: true, comment: '#', commentNoInfix: true}),
tags: Util.getInputList('tags', {ignoreComma: true, comment: '#', commentNoInfix: true}),
flavor: Util.getInputList('flavor', {ignoreComma: true, comment: '#', commentNoInfix: true}),
labels: Util.getInputList('labels', {ignoreComma: true, comment: '#', commentNoInfix: true}),
annotations: Util.getInputList('annotations', {ignoreComma: true, comment: '#', commentNoInfix: true}),
images: Util.getInputList('images', {ignoreComma: true, comment: '#'}),
tags: Util.getInputList('tags', {ignoreComma: true, comment: '#'}),
flavor: Util.getInputList('flavor', {ignoreComma: true, comment: '#'}),
labels: Util.getInputList('labels', {ignoreComma: true, comment: '#'}),
annotations: Util.getInputList('annotations', {ignoreComma: true, comment: '#'}),
sepTags: core.getInput('sep-tags', {trimWhitespace: false}) || `\n`,
sepLabels: core.getInput('sep-labels', {trimWhitespace: false}) || `\n`,
sepAnnotations: core.getInput('sep-annotations', {trimWhitespace: false}) || `\n`,

View file

@ -1,11 +1,11 @@
import * as fs from 'fs';
import * as core from '@actions/core';
import * as actionsToolkit from '@docker/actions-toolkit';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
import {Util} from '@docker/actions-toolkit/lib/util.js';
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
import {Util} from '@docker/actions-toolkit/lib/util';
import {getContext, getInputs, Inputs} from './context.js';
import {Meta, Version} from './meta.js';
import {getContext, getInputs, Inputs} from './context';
import {Meta, Version} from './meta';
actionsToolkit.run(
// main
@ -47,7 +47,7 @@ actionsToolkit.run(
setOutput('version', version.main || '');
// Docker tags
const tags = meta.getTags();
const tags: Array<string> = meta.getTags();
if (tags.length == 0) {
core.warning('No Docker tag has been generated. Check tags input.');
} else {
@ -58,7 +58,6 @@ actionsToolkit.run(
});
}
setOutput('tags', tags.join(inputs.sepTags));
setOutput('tag-names', meta.getTags(true).join(inputs.sepTags));
// Docker labels
const labels: Array<string> = meta.getLabels();

View file

@ -5,13 +5,13 @@ import moment from 'moment-timezone';
import * as pep440 from '@renovate/pep440';
import * as semver from 'semver';
import * as core from '@actions/core';
import {Context as ToolkitContext} from '@docker/actions-toolkit/lib/context.js';
import {GitHubRepo} from '@docker/actions-toolkit/lib/types/github/github.js';
import {Context as ToolkitContext} from '@docker/actions-toolkit/lib/context';
import {GitHubRepo} from '@docker/actions-toolkit/lib/types/github';
import {Inputs, Context} from './context.js';
import * as icl from './image.js';
import * as tcl from './tag.js';
import * as fcl from './flavor.js';
import {Inputs, Context} from './context';
import * as icl from './image';
import * as tcl from './tag';
import * as fcl from './flavor';
const defaultShortShaLength = 7;
@ -161,20 +161,8 @@ export class Meta {
if (tag.attrs['value'].length > 0) {
vraw = this.setGlobalExp(tag.attrs['value']);
} else {
vraw = this.context.ref.replace(/^refs\/tags\//g, '');
vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-');
}
if (tag.attrs['match'].length > 0) {
const tmatch = vraw.match(tag.attrs['match']);
if (!tmatch) {
core.warning(`${tag.attrs['match']} does not match ${vraw}.`);
} else {
vraw = tmatch[1];
}
}
vraw = vraw.replace(/\//g, '-');
if (!semver.valid(vraw)) {
core.warning(`${vraw} is not a valid semver. More info: https://semver.org/`);
return version;
@ -207,20 +195,8 @@ export class Meta {
if (tag.attrs['value'].length > 0) {
vraw = this.setGlobalExp(tag.attrs['value']);
} else {
vraw = this.context.ref.replace(/^refs\/tags\//g, '');
vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-');
}
if (tag.attrs['match'].length > 0) {
const tmatch = vraw.match(tag.attrs['match']);
if (!tmatch) {
core.warning(`${tag.attrs['match']} does not match ${vraw}.`);
} else {
vraw = tmatch[1];
}
}
vraw = vraw.replace(/\//g, '-');
if (!pep440.valid(vraw)) {
core.warning(`${vraw} does not conform to PEP 440. More info: https://www.python.org/dev/peps/pep-0440`);
return version;
@ -376,7 +352,7 @@ export class Meta {
if (hp.body.length == 1 && hp.body[0].type == 'MustacheStatement') {
return hp.body[0]['path']['parts'].length == 1 && hp.body[0]['path']['parts'][0] == 'raw';
}
} catch {
} catch (err) {
return false;
}
return false;
@ -463,9 +439,6 @@ export class Meta {
}
return 'false';
},
is_not_default_branch: function () {
return this.is_default_branch() === 'false' ? 'true' : 'false';
},
date: function (format, options) {
const m = moment(currentDate);
let tz = 'UTC';
@ -494,37 +467,33 @@ export class Meta {
return images;
}
public getTags(namesOnly?: boolean): Array<string> {
public getTags(): Array<string> {
if (!this.version.main) {
return [];
}
if (namesOnly) {
return this.generateTags(this.version.main);
}
const generateTags = (imageName: string, version: string): Array<string> => {
const tags: Array<string> = [];
const prefix = imageName !== '' ? `${imageName}:` : '';
tags.push(`${prefix}${version}`);
for (const partial of this.version.partial) {
tags.push(`${prefix}${partial}`);
}
if (this.version.latest) {
const latestTag = `${this.flavor.prefixLatest ? this.flavor.prefix : ''}latest${this.flavor.suffixLatest ? this.flavor.suffix : ''}`;
tags.push(`${prefix}${Meta.sanitizeTag(latestTag)}`);
}
return tags;
};
const tags: Array<string> = [];
const images = this.getImageNames();
if (images.length > 0) {
for (const imageName of images) {
tags.push(...this.generateTags(this.version.main, imageName));
tags.push(...generateTags(imageName, this.version.main));
}
} else {
tags.push(...this.generateTags(this.version.main));
}
return tags;
}
private generateTags(version: string, imageName?: string): Array<string> {
const tags: Array<string> = [];
const prefix = imageName ? `${imageName}:` : '';
tags.push(`${prefix}${version}`);
for (const partial of this.version.partial) {
tags.push(`${prefix}${partial}`);
}
if (this.version.latest) {
const latestTag = `${this.flavor.prefixLatest ? this.flavor.prefix : ''}latest${this.flavor.suffixLatest ? this.flavor.suffix : ''}`;
tags.push(`${prefix}${Meta.sanitizeTag(latestTag)}`);
tags.push(...generateTags('', this.version.main));
}
return tags;
}
@ -572,7 +541,6 @@ export class Meta {
}
return {
tags: this.getTags(),
'tag-names': this.getTags(true),
labels: this.getLabels().reduce((res, label) => {
const matches = label.match(/([^=]*)=(.*)/);
if (!matches) {

View file

@ -104,10 +104,10 @@ export function Parse(s: string): Tag {
const value = parts[1];
switch (key) {
case 'type': {
if (!Object.values(Type).includes(value as Type)) {
if (!Object.values(Type).includes(value)) {
throw new Error(`Unknown tag type attribute: ${value}`);
}
tag.type = value as Type;
tag.type = value;
break;
}
default: {
@ -137,9 +137,6 @@ export function Parse(s: string): Tag {
if (!Object.prototype.hasOwnProperty.call(tag.attrs, 'value')) {
tag.attrs['value'] = '';
}
if (!Object.prototype.hasOwnProperty.call(tag.attrs, 'match')) {
tag.attrs['match'] = '';
}
break;
}
case Type.Match: {

View file

@ -1,8 +1,9 @@
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"esModuleInterop": true,
"target": "es6",
"module": "commonjs",
"strict": true,
"newLine": "lf",
"outDir": "./lib",
"rootDir": "./src",
@ -11,7 +12,11 @@
"resolveJsonModule": true,
"useUnknownInCatchVariables": false,
},
"include": [
"src/**/*.ts"
"exclude": [
"./__mocks__/**/*",
"./__tests__/**/*",
"./lib/**/*",
"node_modules",
"jest.config.ts"
]
}

View file

@ -1,16 +0,0 @@
import {defineConfig} from 'vitest/config';
export default defineConfig({
test: {
clearMocks: true,
environment: 'node',
setupFiles: ['./__tests__/setup.unit.ts'],
include: ['**/*.test.ts'],
coverage: {
provider: 'v8',
reporter: ['clover'],
include: ['src/**/*.ts'],
exclude: ['src/**/main.ts']
}
}
});

7494
yarn.lock

File diff suppressed because it is too large Load diff