Compare commits

..

21 Commits

Author SHA1 Message Date
CrazyMax 9e3d36ea10 chore: update generated content
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-07-22 13:01:47 +02:00
CrazyMax 14d6a7934e docker hub oidc support
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-07-22 13:01:46 +02:00
CrazyMax 03c851098f Merge pull request #1044 from docker/dependabot/npm_and_yarn/docker/actions-toolkit-0.93.0
build(deps): bump @docker/actions-toolkit from 0.92.0 to 0.93.0
2026-07-22 08:53:04 +02:00
CrazyMax ad8a81f098 Merge pull request #1046 from docker/dependabot/npm_and_yarn/brace-expansion-1.1.16
build(deps): bump brace-expansion from 1.1.13 to 1.1.16
2026-07-22 08:51:57 +02:00
github-actions[bot] 6d219a4928 [dependabot skip] chore: update generated content 2026-07-22 06:51:44 +00:00
dependabot[bot] b3200694f4 build(deps): bump @docker/actions-toolkit from 0.92.0 to 0.93.0
Bumps [@docker/actions-toolkit](https://github.com/docker/actions-toolkit) from 0.92.0 to 0.93.0.
- [Release notes](https://github.com/docker/actions-toolkit/releases)
- [Commits](https://github.com/docker/actions-toolkit/compare/v0.92.0...v0.93.0)

---
updated-dependencies:
- dependency-name: "@docker/actions-toolkit"
  dependency-version: 0.93.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-22 06:50:49 +00:00
github-actions[bot] 08d3680aa8 [dependabot skip] chore: update generated content 2026-07-22 06:50:38 +00:00
CrazyMax 381f5a4f5e Merge pull request #1042 from docker/dependabot/github_actions/codeql-actions-af2beed448
build(deps): bump the codeql-actions group with 2 updates
2026-07-22 08:49:44 +02:00
dependabot[bot] 4bc69ce4fd build(deps): bump brace-expansion from 1.1.13 to 1.1.16
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.13 to 1.1.16.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.13...v1.1.16)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.16
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-22 06:49:44 +00:00
CrazyMax ddf94996dc Merge pull request #1043 from docker/dependabot/github_actions/actions/setup-node-7.0.0
build(deps): bump actions/setup-node from 6.4.0 to 7.0.0
2026-07-22 08:49:18 +02:00
CrazyMax d870eb57d3 Merge pull request #1045 from docker/dependabot/github_actions/actions/checkout-7.0.1
build(deps): bump actions/checkout from 7.0.0 to 7.0.1
2026-07-22 08:48:31 +02:00
CrazyMax 4d7b1348c8 Merge pull request #1038 from docker/dependabot/npm_and_yarn/js-yaml-5.2.1
build(deps): bump js-yaml from 5.2.0 to 5.2.1
2026-07-22 08:47:43 +02:00
dependabot[bot] 608836776e build(deps): bump actions/checkout from 7.0.0 to 7.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 05:52:59 +00:00
dependabot[bot] 3bab31f360 build(deps): bump actions/setup-node from 6.4.0 to 7.0.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.4.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-15 05:52:18 +00:00
dependabot[bot] dc654b7be1 build(deps): bump the codeql-actions group with 2 updates
Bumps the codeql-actions group with 2 updates: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.36.2 to 4.36.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/8aad20d150bbac5944a9f9d289da16a4b0d87c1e...54f647b7e1bb85c95cddabcd46b0c578ec92bc1a)

Updates `github/codeql-action/analyze` from 4.36.2 to 4.36.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/8aad20d150bbac5944a9f9d289da16a4b0d87c1e...54f647b7e1bb85c95cddabcd46b0c578ec92bc1a)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 12:01:00 +00:00
CrazyMax c66a8fcb24 Merge pull request #1041 from crazy-max/group-codeql-dependabot-updates
chore: group codeql dependabot updates
2026-07-09 13:57:49 +02:00
CrazyMax 6d7f9d458a chore: group codeql dependabot updates
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-07-09 12:43:17 +02:00
CrazyMax 13169716da Merge pull request #1040 from docker/dependabot/github_actions/aws-actions/configure-aws-credentials-6.2.2
build(deps): bump aws-actions/configure-aws-credentials from 6.2.1 to 6.2.2
2026-07-09 10:17:14 +02:00
dependabot[bot] c1aa9e5f45 build(deps): bump aws-actions/configure-aws-credentials
Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 6.2.1 to 6.2.2.
- [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases)
- [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md)
- [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/254c19bd240aabef8777f48595e9d2d7b972184b...517a711dbcd0e402f90c77e7e2f81e849156e31d)

---
updated-dependencies:
- dependency-name: aws-actions/configure-aws-credentials
  dependency-version: 6.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 05:53:39 +00:00
github-actions[bot] 026f3975fd [dependabot skip] chore: update generated content 2026-07-06 05:55:36 +00:00
dependabot[bot] 3dbb99fd00 build(deps): bump js-yaml from 5.2.0 to 5.2.1
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 5.2.0 to 5.2.1.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/5.2.0...5.2.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 5.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 05:54:34 +00:00
16 changed files with 555 additions and 179 deletions
+3
View File
@@ -10,6 +10,9 @@ updates:
crazy-max-dot-github:
patterns:
- "crazy-max/.github/*"
codeql-actions:
patterns:
- "github/codeql-action/*"
labels:
- "dependencies"
- "bot"
+50 -27
View File
@@ -25,7 +25,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Stop docker
run: |
@@ -49,7 +49,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to GitHub Container Registry
uses: ./
@@ -67,7 +67,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to GitHub Container Registry
uses: ./
@@ -97,7 +97,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to GitHub Container Registry
uses: ./
@@ -122,7 +122,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to ACR
uses: ./
@@ -142,7 +142,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to Docker Hub
uses: ./
@@ -150,6 +150,29 @@ jobs:
username: ${{ vars.DOCKERPUBLICBOT_USERNAME }}
password: ${{ secrets.DOCKERPUBLICBOT_READ_PAT }}
dockerhub-oidc:
permissions:
contents: read
id-token: write
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
steps:
-
name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to Docker Hub with OIDC
uses: ./
env:
DOCKERHUB_OIDC_CONNECTIONID: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }}
with:
username: ${{ vars.DOCKERHUB_OIDC_USERNAME }}
ecr:
runs-on: ${{ matrix.os }}
strategy:
@@ -161,7 +184,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to ECR
uses: ./
@@ -181,10 +204,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -209,10 +232,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with:
role-to-assume: arn:aws:iam::175142243308:role/official_gha_cicd_login_action
aws-region: us-east-1
@@ -233,7 +256,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to Public ECR
continue-on-error: ${{ matrix.os == 'windows-latest' }}
@@ -256,10 +279,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -285,10 +308,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with:
role-to-assume: arn:aws:iam::175142243308:role/official_gha_cicd_login_action
aws-region: us-east-1
@@ -310,7 +333,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to GitHub Container Registry
uses: ./
@@ -330,7 +353,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to GitLab
uses: ./
@@ -350,7 +373,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to Google Artifact Registry
uses: ./
@@ -370,7 +393,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to Google Container Registry
uses: ./
@@ -384,7 +407,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to registries
uses: ./
@@ -407,7 +430,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to registries
uses: ./
@@ -428,7 +451,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to registries
id: login
@@ -460,7 +483,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to Docker Hub
uses: ./
@@ -490,7 +513,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to Docker Hub
uses: ./
@@ -520,7 +543,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to GitHub Container Registry
uses: ./
@@ -551,7 +574,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Login to GitHub Container Registry
uses: ./
+4 -4
View File
@@ -22,7 +22,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Enable corepack
run: |
@@ -30,17 +30,17 @@ jobs:
yarn --version
-
name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ env.NODE_VERSION }}
-
name: Initialize CodeQL
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
with:
languages: javascript-typescript
build-mode: none
-
name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
with:
category: "/language:javascript-typescript"
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Publish
uses: actions/publish-immutable-action@4bc8754ffc40f27910afb20287dbbbb675a4e978 # v0.0.4
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Test
uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7.3.0
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
permission-contents: write
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Generate matrix
id: generate
+40
View File
@@ -28,6 +28,7 @@ ___
* [Set scopes for the authentication token](#set-scopes-for-the-authentication-token)
* [Customizing](#customizing)
* [inputs](#inputs)
* [environment variables](#environment-variables)
* [Contributing](#contributing)
## Usage
@@ -57,6 +58,36 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
```
You can also [authenticate to Docker Hub with OpenID Connect](https://docs.docker.com/enterprise/security/oidc-connections/)
when your Docker Hub organization has an OIDC connection configured. The
workflow must grant the `id-token: write` permission, pass the Docker Hub
organization name as `username`, omit `password`, and set the OIDC connection
ID in `DOCKERHUB_OIDC_CONNECTIONID` environment variable.
```yaml
name: ci
on:
push:
branches: main
permissions:
contents: read
id-token: write
jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Login to Docker Hub
uses: docker/login-action@v4
env:
DOCKERHUB_OIDC_CONNECTIONID: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }}
with:
username: ${{ vars.DOCKERHUB_ORGANIZATION }}
```
### GitHub Container Registry
To authenticate to the [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry),
@@ -690,6 +721,15 @@ The following inputs can be used as `step.with` keys:
> [!NOTE]
> The `registry-auth` input cannot be used with other inputs except `logout`.
### environment variables
The following environment variables can be set as `step.env` keys:
| Name | Type | Default | Description |
|-------------------------------|--------|---------|-----------------------------------------------------------------------------|
| `DOCKERHUB_OIDC_CONNECTIONID` | String | | Docker Hub OIDC connection ID. Required for Docker Hub OIDC login |
| `DOCKERHUB_OIDC_EXPIREIN` | Number | `300` | Docker Hub OIDC token lifetime in seconds. Must be between `300` and `3600` |
## Contributing
Want to contribute? Awesome! You can find information about contributing to
+133
View File
@@ -0,0 +1,133 @@
import * as core from '@actions/core';
import * as httpm from '@actions/http-client';
import {beforeEach, describe, expect, test, vi} from 'vitest';
import * as dockerhub from '../src/dockerhub.js';
vi.mock('@actions/core', () => ({
getIDToken: vi.fn(),
info: vi.fn(),
setSecret: vi.fn()
}));
const validConnectionID = '123e4567-e89b-42d3-a456-426614174000';
const httpResponse = (statusCode: number, body: string, headers: Record<string, string> = {}): httpm.HttpClientResponse => {
return {
message: {
statusCode,
headers
},
readBody: vi.fn(async () => body)
} as unknown as httpm.HttpClientResponse;
};
describe('isDockerHubOIDC', () => {
beforeEach(() => {
delete process.env.DOCKERHUB_OIDC_CONNECTIONID;
});
test.each(['', 'docker.io', 'registry-1.docker.io', 'registry-1-stage.docker.io'])('detects Docker Hub registry %p with empty password', registry => {
process.env.DOCKERHUB_OIDC_CONNECTIONID = validConnectionID;
expect(dockerhub.isDockerHubOIDC(registry, '')).toBe(true);
});
test('requires connection ID env var', () => {
expect(dockerhub.isDockerHubOIDC('docker.io', '')).toBe(false);
});
test('requires empty password', () => {
process.env.DOCKERHUB_OIDC_CONNECTIONID = validConnectionID;
expect(dockerhub.isDockerHubOIDC('docker.io', 'groundcontrol')).toBe(false);
});
test('ignores non-Docker Hub registries', () => {
process.env.DOCKERHUB_OIDC_CONNECTIONID = validConnectionID;
expect(dockerhub.isDockerHubOIDC('ghcr.io', '')).toBe(false);
});
});
describe('getOIDCToken', () => {
const getIDTokenMock = vi.mocked(core.getIDToken);
const setSecretMock = vi.mocked(core.setSecret);
let postSpy: ReturnType<typeof vi.spyOn>;
beforeEach(() => {
process.env.DOCKERHUB_OIDC_CONNECTIONID = validConnectionID;
delete process.env.DOCKERHUB_OIDC_EXPIREIN;
getIDTokenMock.mockResolvedValue('github-id-token');
postSpy = vi.spyOn(httpm.HttpClient.prototype, 'post').mockResolvedValue(httpResponse(200, JSON.stringify({access_token: 'hub-token'})));
});
test('exchanges GitHub OIDC token for Docker Hub token', async () => {
const credentials = await dockerhub.getOIDCToken('docker.io', 'dbowie');
expect(credentials).toEqual({
username: 'dbowie',
token: 'hub-token'
});
expect(getIDTokenMock).toHaveBeenCalledWith('https://identity.docker.com');
expect(postSpy).toHaveBeenCalledTimes(1);
expect(postSpy.mock.calls[0][0]).toBe('https://identity.docker.com/oauth/token');
const http = postSpy.mock.contexts[0] as httpm.HttpClient;
expect(http.userAgent).toBe('github.com/docker/login-action');
expect(http.requestOptions?.headers).toEqual({
'Content-Type': 'application/x-www-form-urlencoded'
});
const body = new URLSearchParams(postSpy.mock.calls[0][1]);
expect(body.get('grant_type')).toBe('urn:ietf:params:oauth:grant-type:token-exchange');
expect(body.get('subject_token_type')).toBe('urn:ietf:params:oauth:token-type:id_token');
expect(body.get('subject_token')).toBe('github-id-token');
expect(body.get('connection_id')).toBe(validConnectionID);
expect(body.get('expires_in')).toBe('300');
expect(setSecretMock).toHaveBeenCalledWith('hub-token');
});
test('uses custom token expiration', async () => {
process.env.DOCKERHUB_OIDC_EXPIREIN = '900';
await dockerhub.getOIDCToken('docker.io', 'dbowie');
const body = new URLSearchParams(postSpy.mock.calls[0][1]);
expect(body.get('expires_in')).toBe('900');
});
test('uses stage identity host for stage registry', async () => {
await dockerhub.getOIDCToken('registry-1-stage.docker.io', 'dbowie');
expect(getIDTokenMock).toHaveBeenCalledWith('https://identity-stage.docker.com');
expect(postSpy.mock.calls[0][0]).toBe('https://identity-stage.docker.com/oauth/token');
});
test('requires connection ID env var', async () => {
delete process.env.DOCKERHUB_OIDC_CONNECTIONID;
await expect(dockerhub.getOIDCToken('docker.io', 'dbowie')).rejects.toThrow('DOCKERHUB_OIDC_CONNECTIONID is required for Docker Hub OIDC login');
expect(getIDTokenMock).not.toHaveBeenCalled();
expect(postSpy).not.toHaveBeenCalled();
});
test('validates connection ID', async () => {
process.env.DOCKERHUB_OIDC_CONNECTIONID = 'not-a-uuid';
await expect(dockerhub.getOIDCToken('docker.io', 'dbowie')).rejects.toThrow('Invalid DOCKERHUB_OIDC_CONNECTIONID. Must be a valid UUID.');
expect(getIDTokenMock).not.toHaveBeenCalled();
expect(postSpy).not.toHaveBeenCalled();
});
test.each(['not-a-number', '299', '3601'])('validates token expiration %p', async expiresIn => {
process.env.DOCKERHUB_OIDC_EXPIREIN = expiresIn;
await expect(dockerhub.getOIDCToken('docker.io', 'dbowie')).rejects.toThrow(`Invalid DOCKERHUB_OIDC_EXPIREIN: ${expiresIn}. Must be between 300 and 3600`);
expect(getIDTokenMock).not.toHaveBeenCalled();
expect(postSpy).not.toHaveBeenCalled();
});
test('retries rate limited token requests with Retry-After', async () => {
postSpy.mockResolvedValueOnce(httpResponse(429, '', {'retry-after': '0'})).mockResolvedValueOnce(httpResponse(200, JSON.stringify({access_token: 'hub-token'})));
await dockerhub.getOIDCToken('docker.io', 'dbowie');
expect(postSpy).toHaveBeenCalledTimes(2);
expect(core.info).toHaveBeenCalledWith('Docker Hub OIDC token request rate limited, retrying in 0ms (attempt 1/5)');
});
test('throws Docker Hub API errors', async () => {
postSpy.mockResolvedValue(httpResponse(400, JSON.stringify({description: 'bad connection'})));
await expect(dockerhub.getOIDCToken('docker.io', 'dbowie')).rejects.toThrow('Docker Hub API: bad status code 400: bad connection');
});
});
Generated Vendored
+118 -114
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+4 -4
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+22 -4
View File
@@ -399,7 +399,7 @@ Apache License
The following npm package may be included in this product:
- @docker/actions-toolkit@0.92.0
- @docker/actions-toolkit@0.93.0
This package contains the following license:
@@ -2398,7 +2398,7 @@ SOFTWARE.
The following npm package may be included in this product:
- js-yaml@5.2.0
- js-yaml@5.2.1
This package contains the following license:
@@ -4590,7 +4590,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
The following npm packages may be included in this product:
- brace-expansion@1.1.13
- brace-expansion@1.1.16
- brace-expansion@2.0.3
These packages each contain the following license:
@@ -5562,7 +5562,7 @@ THE SOFTWARE.
The following npm package may be included in this product:
- csv-parse@7.0.0
- csv-parse@7.0.1
This package contains the following license:
@@ -5590,6 +5590,24 @@ SOFTWARE.
-----------
The following npm package may be included in this product:
- uuid@14.0.1
This package contains the following license:
The MIT License (MIT)
Copyright (c) 2010-2020 Robert Kieffer and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------
The following npm package may be included in this product:
- tunnel@0.0.6
+4 -2
View File
@@ -24,12 +24,14 @@
"packageManager": "yarn@4.15.0",
"dependencies": {
"@actions/core": "^3.0.1",
"@actions/http-client": "^4.0.1",
"@aws-sdk/client-ecr": "^3.1077.0",
"@aws-sdk/client-ecr-public": "^3.1077.0",
"@docker/actions-toolkit": "^0.92.0",
"@docker/actions-toolkit": "^0.93.0",
"http-proxy-agent": "^9.1.0",
"https-proxy-agent": "^9.1.0",
"js-yaml": "^5.2.0"
"js-yaml": "^5.2.1",
"uuid": "^14.0.1"
},
"devDependencies": {
"@eslint/js": "^9.39.3",
+9 -1
View File
@@ -4,12 +4,20 @@ import {Docker} from '@docker/actions-toolkit/lib/docker/docker.js';
import * as aws from './aws.js';
import * as context from './context.js';
import * as dockerhub from './dockerhub.js';
export async function login(auth: context.Auth): Promise<void> {
if (/true/i.test(auth.ecr) || (auth.ecr == 'auto' && aws.isECR(auth.registry))) {
await loginECR(auth.registry, auth.username, auth.password, auth.scope);
} else {
await loginStandard(auth.registry, auth.username, auth.password, auth.scope);
let username = auth.username;
let password = auth.password;
if (dockerhub.isDockerHubOIDC(auth.registry, password)) {
const credentials = await dockerhub.getOIDCToken(auth.registry, username);
username = credentials.username;
password = credentials.token;
}
await loginStandard(auth.registry, username, password, auth.scope);
}
}
+134
View File
@@ -0,0 +1,134 @@
import * as core from '@actions/core';
import * as httpm from '@actions/http-client';
import {HttpCodes} from '@actions/http-client';
import {validate as uuidValidate} from 'uuid';
export interface LoginCredentials {
username: string;
token: string;
}
interface OIDCTokenResponse {
access_token: string;
}
const defaultExpiresIn = 300;
const minExpiresIn = 300;
const maxExpiresIn = 3600;
const maxRetries = 5;
export const isDockerHubOIDC = (registry: string, password: string): boolean => {
return process.env.DOCKERHUB_OIDC_CONNECTIONID !== undefined && !password && isDockerHubRegistry(registry);
};
const isDockerHubRegistry = (registry: string): boolean => {
return registry === '' || registry === 'docker.io' || registry === 'registry-1.docker.io' || registry === 'registry-1-stage.docker.io';
};
export const getOIDCToken = async (registry: string, username: string): Promise<LoginCredentials> => {
const connectionID = process.env.DOCKERHUB_OIDC_CONNECTIONID?.trim();
if (!connectionID) {
throw new Error('DOCKERHUB_OIDC_CONNECTIONID is required for Docker Hub OIDC login');
}
if (!uuidValidate(connectionID)) {
throw new Error('Invalid DOCKERHUB_OIDC_CONNECTIONID. Must be a valid UUID.');
}
const expiresIn = getExpiresIn();
const identityHost = registry === 'registry-1-stage.docker.io' ? 'identity-stage.docker.com' : 'identity.docker.com';
const audience = `https://${identityHost}`;
const idToken = await core.getIDToken(audience);
const http: httpm.HttpClient = new httpm.HttpClient('github.com/docker/login-action', [], {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const data = new URLSearchParams();
data.set('grant_type', 'urn:ietf:params:oauth:grant-type:token-exchange');
data.set('subject_token_type', 'urn:ietf:params:oauth:token-type:id_token');
data.set('subject_token', idToken);
data.set('connection_id', connectionID);
data.set('expires_in', expiresIn.toString());
const resp = await postWithRetry(http, `https://${identityHost}/oauth/token`, data.toString());
const tokenResp = <OIDCTokenResponse>JSON.parse(await handleResponse(resp));
core.setSecret(tokenResp.access_token);
return {
username,
token: tokenResp.access_token
};
};
const getExpiresIn = (): number => {
const expiresInInput = process.env.DOCKERHUB_OIDC_EXPIREIN?.trim() || defaultExpiresIn.toString();
const expiresIn = Number(expiresInInput);
if (isNaN(expiresIn) || expiresIn < minExpiresIn || expiresIn > maxExpiresIn) {
throw new Error(`Invalid DOCKERHUB_OIDC_EXPIREIN: ${expiresInInput}. Must be between ${minExpiresIn} and ${maxExpiresIn}`);
}
return expiresIn;
};
const postWithRetry = async (http: httpm.HttpClient, url: string, data: string): Promise<httpm.HttpClientResponse> => {
let resp = await http.post(url, data);
for (let attempt = 0; (resp.message.statusCode || HttpCodes.InternalServerError) === HttpCodes.TooManyRequests && attempt < maxRetries; attempt++) {
const delay = parseRetryAfter(resp.message.headers['retry-after']);
if (delay === null) {
break;
}
await resp.readBody();
core.info(`Docker Hub OIDC token request rate limited, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
resp = await http.post(url, data);
}
return resp;
};
const parseRetryAfter = (value: string | string[] | undefined): number | null => {
if (value === undefined) {
return null;
}
if (Array.isArray(value)) {
value = value[0];
}
const seconds = Number(value);
if (isNaN(seconds)) {
return null;
}
return Math.max(0, seconds * 1000);
};
const handleResponse = async (resp: httpm.HttpClientResponse): Promise<string> => {
const body = await resp.readBody();
const statusCode = resp.message.statusCode || HttpCodes.InternalServerError;
if (statusCode < HttpCodes.OK || statusCode >= HttpCodes.MultipleChoices) {
throw parseError(statusCode, body);
}
return body;
};
const parseError = (statusCode: number, body: string): Error => {
if (statusCode === 401) {
throw new Error(`Docker Hub API: operation not permitted`);
}
if (body) {
const errResp = parseErrorBody(body);
for (const k of ['description', 'message', 'detail', 'error']) {
if (errResp[k]) {
throw new Error(`Docker Hub API: bad status code ${statusCode}: ${errResp[k]}`);
}
}
}
throw new Error(`Docker Hub API: bad status code ${statusCode}`);
};
const parseErrorBody = (body: string): Record<string, string> => {
try {
return <Record<string, string>>JSON.parse(body);
} catch {
return {};
}
};
+30 -19
View File
@@ -677,9 +677,9 @@ __metadata:
languageName: node
linkType: hard
"@docker/actions-toolkit@npm:^0.92.0":
version: 0.92.0
resolution: "@docker/actions-toolkit@npm:0.92.0"
"@docker/actions-toolkit@npm:^0.93.0":
version: 0.93.0
resolution: "@docker/actions-toolkit@npm:0.93.0"
dependencies:
"@actions/artifact": "npm:^6.2.1"
"@actions/cache": "npm:^6.1.0"
@@ -693,16 +693,16 @@ __metadata:
"@sigstore/tuf": "npm:^5.0.0"
"@sigstore/verify": "npm:^4.1.0"
async-retry: "npm:^1.3.3"
csv-parse: "npm:^7.0.0"
csv-parse: "npm:^7.0.1"
gunzip-maybe: "npm:^1.4.2"
handlebars: "npm:^4.7.9"
he: "npm:^1.2.0"
js-yaml: "npm:^5.2.0"
js-yaml: "npm:^5.2.1"
jwt-decode: "npm:^4.0.0"
semver: "npm:^7.8.5"
tar-stream: "npm:^3.2.0"
tmp: "npm:^0.2.7"
checksum: 10/599cea84b897069c53744a2f05371c6d9ad60da18448b4431273529b92fd2d77ddc718ee205cf0bf1da53083d412da90b1067f1e64a5fdac73fe71d486726064
checksum: 10/31643db575faf865666247661007d6e5fc8bc2b737001a522879829fcbeeab7b11b886d2cc26d074a26814361ec8427484d7b94ad9155d52c41398a7dc27000e
languageName: node
linkType: hard
@@ -2762,12 +2762,12 @@ __metadata:
linkType: hard
"brace-expansion@npm:^1.1.7":
version: 1.1.13
resolution: "brace-expansion@npm:1.1.13"
version: 1.1.16
resolution: "brace-expansion@npm:1.1.16"
dependencies:
balanced-match: "npm:^1.0.0"
concat-map: "npm:0.0.1"
checksum: 10/b5f4329fdbe9d2e25fa250c8f866ebd054ba946179426e99b86dcccddabdb1d481f0e40ee5430032e62a7d0a6c2837605ace6783d015aa1d65d85ca72154d936
checksum: 10/94498bead66c51536df5b7bf1b0a0e581a5b7f86888be10481d06920c4bd9d976e003b13a3d19fddc733f21a09d162ff72f90e18b2c9d062b15121e973d0e13b
languageName: node
linkType: hard
@@ -3103,10 +3103,10 @@ __metadata:
languageName: node
linkType: hard
"csv-parse@npm:^7.0.0":
version: 7.0.0
resolution: "csv-parse@npm:7.0.0"
checksum: 10/53c96e6b4ff80047713bb4d2967d06495890d4b628284a80271860be089fdb5a74cd97c76fd535a00ad26b11cc6e4fc5a243658e5377c0a6334ddd104620d169
"csv-parse@npm:^7.0.1":
version: 7.0.1
resolution: "csv-parse@npm:7.0.1"
checksum: 10/5c914f01181dbb381068b98e17b49361d853faa95db3e8e82bc96b6a0de5313ecc8325a77db35ff66644d7747099965ba3167ec21bd9ce4500edf21b5bdd49bf
languageName: node
linkType: hard
@@ -3155,9 +3155,10 @@ __metadata:
resolution: "docker-login@workspace:."
dependencies:
"@actions/core": "npm:^3.0.1"
"@actions/http-client": "npm:^4.0.1"
"@aws-sdk/client-ecr": "npm:^3.1077.0"
"@aws-sdk/client-ecr-public": "npm:^3.1077.0"
"@docker/actions-toolkit": "npm:^0.92.0"
"@docker/actions-toolkit": "npm:^0.93.0"
"@eslint/js": "npm:^9.39.3"
"@types/js-yaml": "npm:^4.0.9"
"@types/node": "npm:^24.11.0"
@@ -3173,9 +3174,10 @@ __metadata:
globals: "npm:^17.3.0"
http-proxy-agent: "npm:^9.1.0"
https-proxy-agent: "npm:^9.1.0"
js-yaml: "npm:^5.2.0"
js-yaml: "npm:^5.2.1"
prettier: "npm:^3.8.1"
typescript: "npm:^5.9.3"
uuid: "npm:^14.0.1"
vitest: "npm:^4.0.18"
languageName: unknown
linkType: soft
@@ -4344,14 +4346,14 @@ __metadata:
languageName: node
linkType: hard
"js-yaml@npm:^5.2.0":
version: 5.2.0
resolution: "js-yaml@npm:5.2.0"
"js-yaml@npm:^5.2.1":
version: 5.2.1
resolution: "js-yaml@npm:5.2.1"
dependencies:
argparse: "npm:^2.0.1"
bin:
js-yaml: bin/js-yaml.mjs
checksum: 10/8a5e55c5d0fcafae4ac02114a99dc070048b8e5a82a056089ce1f69f8a00fd8eb05b622e76ad50aac1f9d409010636c9616c6b2ed4e58dae138379a60d301220
checksum: 10/e1eca2d21c15572585bb236d9fde31d6789eb50b9c63e8753fa7e0777bc480f7521cad517bd7a0c66f27dfc27ddcd7100beeefa51c1a50e10e98f2e009633c3d
languageName: node
linkType: hard
@@ -6300,6 +6302,15 @@ __metadata:
languageName: node
linkType: hard
"uuid@npm:^14.0.1":
version: 14.0.1
resolution: "uuid@npm:14.0.1"
bin:
uuid: dist-node/bin/uuid
checksum: 10/0f978fd5b0269d7acb615342aeb131f0b8d85eeb8ec34f2915d906baa3befcc14a079a430d0f8116aec6fd20c850cbfab65d1b3d1643fa81ed373c0cf9574f18
languageName: node
linkType: hard
"validate-npm-package-name@npm:^7.0.0":
version: 7.0.2
resolution: "validate-npm-package-name@npm:7.0.2"