Compare commits

..

No commits in common. "v3" and "v2" have entirely different histories.
v3 ... v2

37 changed files with 12304 additions and 19235 deletions

View File

@ -1,12 +1,2 @@
/coverage
# Dependency directories
node_modules/
jspm_packages/
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
/node_modules

View File

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

View File

@ -1,12 +1,11 @@
{
"env": {
"node": true,
"es6": true,
"es2021": true,
"jest": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest/recommended",
"plugin:prettier/recommended"

2
.gitattributes vendored
View File

@ -1,4 +1,2 @@
/.yarn/releases/** binary
/.yarn/plugins/** binary
/dist/** linguist-generated=true
/lib/** linguist-generated=true

1
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1 @@
* @crazy-max

View File

@ -1,3 +0,0 @@
# Code of conduct
- [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines)

View File

@ -1,101 +0,0 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: Bug Report
description: Report a bug
labels:
- status/triage
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to report a bug!
If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com).
- type: checkboxes
attributes:
label: Contributing guidelines
description: >
Make sure you've read the contributing guidelines before proceeding.
options:
- label: I've read the [contributing guidelines](https://github.com/docker/login-action/blob/master/.github/CONTRIBUTING.md) and wholeheartedly agree
required: true
- type: checkboxes
attributes:
label: "I've found a bug, and:"
description: |
Make sure that your request fulfills all of the following requirements.
If one requirement cannot be satisfied, explain in detail why.
options:
- label: The documentation does not mention anything about my problem
- label: There are no open or closed issues that are related to my problem
- type: textarea
attributes:
label: Description
description: >
Provide a brief description of the bug in 1-2 sentences.
validations:
required: true
- type: textarea
attributes:
label: Expected behaviour
description: >
Describe precisely what you'd expect to happen.
validations:
required: true
- type: textarea
attributes:
label: Actual behaviour
description: >
Describe precisely what is actually happening.
validations:
required: true
- type: input
attributes:
label: Repository URL
description: >
Enter the URL of the repository where you are experiencing the
issue. If your repository is private, provide a link to a minimal
repository that reproduces the issue.
- type: input
attributes:
label: Workflow run URL
description: >
Enter the URL of the GitHub Action workflow run if public (e.g.
`https://github.com/<user>/<repo>/actions/runs/<id>`)
- type: textarea
attributes:
label: YAML workflow
description: |
Provide the YAML of the workflow that's causing the issue.
Make sure to remove any sensitive information.
render: yaml
validations:
required: true
- type: textarea
attributes:
label: Workflow logs
description: >
[Attach](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files)
the [log file of your workflow run](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
and make sure to remove any sensitive information.
- type: textarea
attributes:
label: BuildKit logs
description: >
If applicable, provide the [BuildKit container logs](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs)
render: text
- type: textarea
attributes:
label: Additional info
description: |
Provide any additional information that could be useful.

34
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,34 @@
---
name: Bug report
about: Create a report to help us improve
---
### Behaviour
#### Steps to reproduce this issue
1.
2.
3.
#### Expected behaviour
> Tell us what should happen
#### Actual behaviour
> Tell us what happens instead
### Configuration
* Repository URL (if public):
* Build URL (if public):
```yml
# paste your YAML workflow file here and remove sensitive data
```
### Logs
> Download the [log file of your build](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
> and [attach it](https://docs.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue.

View File

@ -1,9 +0,0 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
blank_issues_enabled: true
contact_links:
- name: Questions and Discussions
url: https://github.com/docker/login-action/discussions/new
about: Use Github Discussions to ask questions and/or open discussion topics.
- name: Documentation
url: https://docs.docker.com/build/ci/github-actions/
about: Read the documentation.

View File

@ -1,15 +0,0 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: Feature request
description: Missing functionality? Come tell us about it!
labels:
- kind/enhancement
- status/triage
body:
- type: textarea
id: description
attributes:
label: Description
description: What is the feature you want to see?
validations:
required: true

12
.github/SECURITY.md vendored
View File

@ -1,12 +0,0 @@
# Reporting security issues
The project maintainers take security seriously. If you discover a security
issue, please bring it to their attention right away!
**Please _DO NOT_ file a public issue**, instead send your report privately to
[security@docker.com](mailto:security@docker.com).
Security reports are greatly appreciated, and we will publicly thank you for it.
We also like to send gifts&mdash;if you'd like Docker swag, make sure to let
us know. We currently do not offer a paid security bounty program, but are not
ruling it out in the future.

29
.github/SUPPORT.md vendored Normal file
View File

@ -0,0 +1,29 @@
# Support [![](https://isitmaintained.com/badge/resolution/docker/login-action.svg)](https://isitmaintained.com/project/docker/login-action)
## Reporting an issue
Please do a search in [open issues](https://github.com/docker/login-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
:+1: - upvote
:-1: - downvote
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
## Writing good bug reports and feature requests
File a single issue per problem and feature request.
* Do not enumerate multiple bugs or feature requests in the same issue.
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
You are now ready to [create a new issue](https://github.com/docker/login-action/issues/new/choose)!
## Closure policy
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
* Issues that go a week without a response from original poster are subject to closure at our discretion.

View File

@ -11,14 +11,6 @@ updates:
directory: "/"
schedule:
interval: "daily"
versioning-strategy: "increase"
groups:
aws-sdk-dependencies:
patterns:
- "*aws-sdk*"
proxy-agent-dependencies:
patterns:
- "*-proxy-agent"
allow:
- dependency-type: "production"
labels:

View File

@ -1,9 +1,5 @@
name: ci
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_dispatch:
schedule:
@ -19,7 +15,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Stop docker
run: |
@ -43,7 +39,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to GitHub Container Registry
uses: ./
@ -60,7 +56,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to GitHub Container Registry
uses: ./
@ -85,7 +81,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to ACR
uses: ./
@ -105,7 +101,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to Docker Hub
uses: ./
@ -124,7 +120,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to ECR
uses: ./
@ -144,10 +140,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@ -169,10 +165,9 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to Public ECR
continue-on-error: ${{ matrix.os == 'windows-latest' }}
uses: ./
with:
registry: public.ecr.aws
@ -192,17 +187,16 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
-
name: Login to Public ECR
continue-on-error: ${{ matrix.os == 'windows-latest' }}
name: Login to ECR
uses: ./
with:
registry: public.ecr.aws
@ -218,7 +212,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to GitHub Container Registry
uses: ./
@ -238,7 +232,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to GitLab
uses: ./
@ -258,7 +252,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to Google Artifact Registry
uses: ./
@ -278,7 +272,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Login to Google Container Registry
uses: ./

View File

@ -1,50 +0,0 @@
name: codeql
on:
push:
branches:
- 'master'
- 'releases/v*'
paths:
- '.github/workflows/codeql.yml'
- 'dist/**'
- 'src/**'
pull_request:
paths:
- '.github/workflows/codeql.yml'
- 'dist/**'
- 'src/**'
permissions:
actions: read
contents: read
security-events: write
jobs:
analyze:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language:
- javascript-typescript
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config: |
paths:
- src
-
name: Autobuild
uses: github/codeql-action/autobuild@v3
-
name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@ -1,9 +1,5 @@
name: test
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
@ -17,15 +13,14 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Test
uses: docker/bake-action@v5
uses: docker/bake-action@v3
with:
targets: test
-
name: Upload coverage
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v3
with:
file: ./coverage/clover.xml
token: ${{ secrets.CODECOV_TOKEN }}

View File

@ -1,9 +1,5 @@
name: validate
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
@ -19,7 +15,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Targets matrix
id: targets
@ -37,9 +33,9 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Validate
uses: docker/bake-action@v5
uses: docker/bake-action@v3
with:
targets: ${{ matrix.target }}

66
.gitignore vendored
View File

@ -1,5 +1,7 @@
# https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
node_modules/
lib
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
logs
*.log
@ -7,7 +9,6 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
@ -18,14 +19,34 @@ pids
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
@ -35,19 +56,36 @@ jspm_packages/
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
# dotenv environment variables file
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
.env.test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/

View File

@ -1,6 +0,0 @@
# Dependency directories
node_modules/
jspm_packages/
# yarn v2
.yarn/

View File

@ -1,13 +0,0 @@
logFilters:
- code: YN0013
level: discard
- code: YN0019
level: discard
- code: YN0076
level: discard
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"

208
README.md
View File

@ -23,18 +23,16 @@ ___
* [AWS Public Elastic Container Registry (ECR)](#aws-public-elastic-container-registry-ecr)
* [OCI Oracle Cloud Infrastructure Registry (OCIR)](#oci-oracle-cloud-infrastructure-registry-ocir)
* [Quay.io](#quayio)
* [DigitalOcean](#digitalocean-container-registry)
* [Customizing](#customizing)
* [inputs](#inputs)
* [Contributing](#contributing)
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
## Usage
### Docker Hub
When authenticating to [Docker Hub](https://hub.docker.com) with GitHub Actions,
use a [personal access token](https://docs.docker.com/docker-hub/access-tokens/).
Don't use your account password.
To authenticate against [Docker Hub](https://hub.docker.com) it's strongly recommended to create a
[personal access token](https://docs.docker.com/docker-hub/access-tokens/) as an alternative to your password.
```yaml
name: ci
@ -49,7 +47,7 @@ jobs:
steps:
-
name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@ -57,9 +55,9 @@ jobs:
### 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),
use the [`GITHUB_TOKEN`](https://docs.github.com/en/actions/reference/authentication-in-a-workflow)
secret.
To authenticate against the [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry),
use the [`GITHUB_TOKEN`](https://docs.github.com/en/actions/reference/authentication-in-a-workflow) for the best
security and experience.
```yaml
name: ci
@ -74,7 +72,7 @@ jobs:
steps:
-
name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
@ -102,23 +100,20 @@ jobs:
steps:
-
name: Login to GitLab
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: registry.gitlab.com
username: ${{ secrets.GITLAB_USERNAME }}
password: ${{ secrets.GITLAB_PASSWORD }}
```
If you have [Two-Factor Authentication](https://gitlab.com/help/user/profile/account/two_factor_authentication)
enabled, use a [Personal Access Token](https://gitlab.com/help/user/profile/personal_access_tokens)
instead of a password.
If you have [Two-Factor Authentication](https://gitlab.com/help/user/profile/account/two_factor_authentication) enabled, use a [Personal Access Token](https://gitlab.com/help/user/profile/personal_access_tokens) instead of a password.
### Azure Container Registry (ACR)
[Create a service principal](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-service-principal#create-a-service-principal)
with access to your container registry through the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli)
and take note of the generated service principal's ID (also called _client ID_)
and password (also called _client secret_).
and take note of the generated service principal's ID (also called _client ID_) and password (also called _client secret_).
```yaml
name: ci
@ -133,7 +128,7 @@ jobs:
steps:
-
name: Login to ACR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: <registry-name>.azurecr.io
username: ${{ secrets.AZURE_CLIENT_ID }}
@ -144,21 +139,16 @@ jobs:
### Google Container Registry (GCR)
> [Google Artifact Registry](#google-artifact-registry-gar) is the evolution of
> Google Container Registry. As a fully-managed service with support for both
> container images and non-container artifacts. If you currently use Google
> Container Registry, use the information [on this page](https://cloud.google.com/artifact-registry/docs/transition/transition-from-gcr)
> [Google Artifact Registry](#google-artifact-registry-gar) is the evolution of Google Container Registry. As a
> fully-managed service with support for both container images and non-container artifacts. If you currently use
> Google Container Registry, use the information [on this page](https://cloud.google.com/artifact-registry/docs/transition/transition-from-gcr)
> to learn about transitioning to Google Artifact Registry.
You can authenticate with workload identity federation or a service account.
You can use either workload identity federation based keyless authentication or service account based authentication.
#### Workload identity federation
#### Workload identity federation based authentication
Configure the workload identity federation for GitHub Actions in Google Cloud,
[see here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation).
Your service account must have permission to push to GCR. Use the
`google-github-actions/auth` action to authenticate using workload identity as
shown in the following example:
Configure the workload identity federation for github actions in gcloud (for steps, [refer here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation)). In the steps, your service account should the ability to push to GCR. Then use google-github-actions/auth action for authentication using workload identity like below:
```yaml
name: ci
@ -171,35 +161,32 @@ jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@v1
- id: 'auth'
name: 'Authenticate to Google Cloud'
uses: 'google-github-actions/auth@v0'
with:
token_format: access_token
workload_identity_provider: <workload_identity_provider>
service_account: <service_account>
-
name: Login to GCR
uses: docker/login-action@v3
token_format: 'access_token'
workload_identity_provider: '<workload_identity_provider>'
service_account: '<service_account>'
- name: Login to GCR
uses: docker/login-action@v2
with:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
```
> Replace `<workload_identity_provider>` with configured workload identity
> provider. For steps to configure, [see here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation).
> Replace `<workload_identity_provider>` with configured workload identity provider. For steps to configure, [refer here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation).
> Replace `<service_account>` with configured service account in workload
> identity provider which has access to push to GCR
> Replace `<service_account>` with configured service account in workload identity provider which has access to push to GCR
#### Service account based authentication
Use a service account with permission to push to GCR and [configure access control](https://cloud.google.com/container-registry/docs/access-control).
Download the key for the service account as a JSON file. Save the contents of
the file [as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
named `GCR_JSON_KEY` in your GitHub repository. Set the username to `_json_key`,
Use a service account with the ability to push to GCR and [configure access control](https://cloud.google.com/container-registry/docs/access-control).
Then create and download the JSON key for this service account and save content of `.json` file
[as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
called `GCR_JSON_KEY` in your GitHub repo. Ensure you set the username to `_json_key`,
or `_json_key_base64` if you use a base64-encoded key.
```yaml
@ -215,7 +202,7 @@ jobs:
steps:
-
name: Login to GCR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: gcr.io
username: _json_key
@ -224,13 +211,11 @@ jobs:
### Google Artifact Registry (GAR)
You can authenticate with workload identity federation or a service account.
You can use either workload identity federation based keyless authentication or service account based authentication.
#### Workload identity federation
#### Workload identity federation based authentication
Your service account must have permission to push to GAR. Use the
`google-github-actions/auth` action to authenticate using workload identity as
shown in the following example:
Configure the workload identity federation for github actions in gcloud (for steps, [refer here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation)). In the steps, your service account should the ability to push to GAR. Then use google-github-actions/auth action for authentication using workload identity like below:
```yaml
name: ci
@ -243,38 +228,34 @@ jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@v1
- id: 'auth'
name: 'Authenticate to Google Cloud'
uses: 'google-github-actions/auth@v0'
with:
token_format: access_token
workload_identity_provider: <workload_identity_provider>
service_account: <service_account>
-
name: Login to GAR
uses: docker/login-action@v3
token_format: 'access_token'
workload_identity_provider: '<workload_identity_provider>'
service_account: '<service_account>'
- name: Login to GAR
uses: docker/login-action@v2
with:
registry: <location>-docker.pkg.dev
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
```
> Replace `<workload_identity_provider>` with configured workload identity provider
> Replace `<workload_identity_provider>` with configured workload identity
> provider
> Replace `<service_account>` with configured service account in workload
> identity provider which has access to push to GCR
> Replace `<service_account>` with configured service account in workload identity provider which has access to push to GCR
> Replace `<location>` with the regional or multi-regional [location](https://cloud.google.com/artifact-registry/docs/repo-organize#locations)
> of the repository where the image is stored.
#### Service account based authentication
Use a service account with permission to push to GAR and [configure access control](https://cloud.google.com/artifact-registry/docs/access-control).
Download the key for the service account as a JSON file. Save the contents of
the file [as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
named `GAR_JSON_KEY` in your GitHub repository. Set the username to `_json_key`,
Use a service account with the ability to push to GAR and [configure access control](https://cloud.google.com/artifact-registry/docs/access-control).
Then create and download the JSON key for this service account and save content of `.json` file
[as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
called `GAR_JSON_KEY` in your GitHub repo. Ensure you set the username to `_json_key`,
or `_json_key_base64` if you use a base64-encoded key.
```yaml
@ -290,7 +271,7 @@ jobs:
steps:
-
name: Login to GAR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: <location>-docker.pkg.dev
username: _json_key
@ -303,7 +284,7 @@ jobs:
### AWS Elastic Container Registry (ECR)
Use an IAM user with the ability to [push to ECR with `AmazonEC2ContainerRegistryPowerUser` managed policy for example](https://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html#AmazonEC2ContainerRegistryPowerUser).
Download the access keys and save them as `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [as secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
Then create and download access keys and save `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [as secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
in your GitHub repo.
```yaml
@ -319,15 +300,15 @@ jobs:
steps:
-
name: Login to ECR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: <aws-account-number>.dkr.ecr.<region>.amazonaws.com
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
```
If you need to log in to Amazon ECR registries associated with other accounts,
you can use the `AWS_ACCOUNT_IDS` environment variable:
If you need to log in to Amazon ECR registries associated with other accounts, you can use the `AWS_ACCOUNT_IDS`
environment variable:
```yaml
name: ci
@ -342,7 +323,7 @@ jobs:
steps:
-
name: Login to ECR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: <aws-account-number>.dkr.ecr.<region>.amazonaws.com
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
@ -353,8 +334,8 @@ jobs:
> Only available with [AWS CLI version 1](https://docs.aws.amazon.com/cli/latest/reference/ecr/get-login.html)
You can also use the [Configure AWS Credentials](https://github.com/aws-actions/configure-aws-credentials)
action in combination with this action:
You can also use the [Configure AWS Credentials](https://github.com/aws-actions/configure-aws-credentials) action in
combination with this action:
```yaml
name: ci
@ -369,14 +350,14 @@ jobs:
steps:
-
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: <region>
-
name: Login to ECR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: <aws-account-number>.dkr.ecr.<region>.amazonaws.com
```
@ -385,10 +366,9 @@ jobs:
### AWS Public Elastic Container Registry (ECR)
Use an IAM user with permission to push to ECR Public, for example using [managed policies](https://docs.aws.amazon.com/AmazonECR/latest/userguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonEC2ContainerRegistryPowerUser).
Download the access keys and save them as `AWS_ACCESS_KEY_ID` and
`AWS_SECRET_ACCESS_KEY` [secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
in your GitHub repository.
Use an IAM user with the ability to [push to ECR Public with `AmazonElasticContainerRegistryPublicPowerUser` managed policy for example](https://docs.aws.amazon.com/AmazonECR/latest/public/public-ecr-managed-policies.html#AmazonElasticContainerRegistryPublicPowerUser).
Then create and download access keys and save `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [as secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
in your GitHub repo.
```yaml
name: ci
@ -403,7 +383,7 @@ jobs:
steps:
-
name: Login to Public ECR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: public.ecr.aws
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
@ -437,7 +417,7 @@ jobs:
steps:
-
name: Login to OCIR
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: <region>.ocir.io
username: ${{ secrets.OCI_USERNAME }}
@ -448,8 +428,7 @@ jobs:
### Quay.io
Use a [Robot account](https://docs.quay.io/glossary/robot-accounts.html) with
permission to push to a Quay.io repository.
Use a [Robot account](https://docs.quay.io/glossary/robot-accounts.html) with the ability to push to a public/private Quay.io repository.
```yaml
name: ci
@ -464,52 +443,39 @@ jobs:
steps:
-
name: Login to Quay.io
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
```
### DigitalOcean Container Registry
Use your DigitalOcean registered email address and an API access token to authenticate.
```yaml
name: ci
on:
push:
branches: main
jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Login to DigitalOcean Container Registry
uses: docker/login-action@v3
with:
registry: registry.digitalocean.com
username: ${{ secrets.DIGITALOCEAN_USERNAME }}
password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
```
## Customizing
### inputs
The following inputs can be used as `step.with` keys:
Following inputs can be used as `step.with` keys
| Name | Type | Default | Description |
|------------|--------|---------|-------------------------------------------------------------------------------|
|------------------|---------|-----------------------------|------------------------------------|
| `registry` | String | | Server address of Docker registry. If not set then will default to Docker Hub |
| `username` | String | | Username for authenticating to the Docker registry |
| `password` | String | | Password or personal access token for authenticating the Docker registry |
| `username` | String | | Username used to log against the Docker registry |
| `password` | String | | Password or personal access token used to log against the Docker registry |
| `ecr` | String | `auto` | Specifies whether the given registry is ECR (`auto`, `true` or `false`) |
| `logout` | Bool | `true` | Log out from the Docker registry at the end of a job |
## Contributing
## Keep up-to-date with GitHub Dependabot
Want to contribute? Awesome! You can find information about contributing to
this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md)
Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot)
has [native GitHub Actions support](https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem),
to enable it on your GitHub repo all you need to do is add the `.github/dependabot.yml` file:
```yaml
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
```

View File

@ -1,6 +1,5 @@
import {beforeEach, describe, expect, jest, test} from '@jest/globals';
import {AuthorizationData} from '@aws-sdk/client-ecr';
import * as aws from '../src/aws';
describe('isECR', () => {

View File

@ -1,5 +1,4 @@
import {expect, test} from '@jest/globals';
import {getInputs} from '../src/context';
test('with password and username getInputs does not throw error', async () => {

View File

@ -1,16 +1,14 @@
import {expect, jest, test} from '@jest/globals';
import * as path from 'path';
import {loginStandard, logout} from '../src/docker';
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
import * as path from 'path';
import * as exec from '@actions/exec';
process.env['RUNNER_TEMP'] = path.join(__dirname, 'runner');
test('loginStandard calls exec', async () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const execSpy = jest.spyOn(Docker, 'getExecOutput').mockImplementation(async () => {
const execSpy = jest.spyOn(exec, 'getExecOutput').mockImplementation(async () => {
return {
exitCode: expect.any(Number),
stdout: expect.any(Function),
@ -24,13 +22,7 @@ test('loginStandard calls exec', async () => {
await loginStandard(registry, username, password);
expect(execSpy).toHaveBeenCalledTimes(1);
const callfunc = execSpy.mock.calls[0];
if (callfunc && callfunc[1]) {
// we don't want to check env opt
callfunc[1].env = undefined;
}
expect(execSpy).toHaveBeenCalledWith(['login', '--password-stdin', '--username', username, registry], {
expect(execSpy).toHaveBeenCalledWith(`docker`, ['login', '--password-stdin', '--username', username, registry], {
input: Buffer.from(password),
silent: true,
ignoreReturnCode: true
@ -40,7 +32,7 @@ test('loginStandard calls exec', async () => {
test('logout calls exec', async () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const execSpy = jest.spyOn(Docker, 'getExecOutput').mockImplementation(async () => {
const execSpy = jest.spyOn(exec, 'getExecOutput').mockImplementation(async () => {
return {
exitCode: expect.any(Number),
stdout: expect.any(Function),
@ -52,13 +44,7 @@ test('logout calls exec', async () => {
await logout(registry);
expect(execSpy).toHaveBeenCalledTimes(1);
const callfunc = execSpy.mock.calls[0];
if (callfunc && callfunc[1]) {
// we don't want to check env opt
callfunc[1].env = undefined;
}
expect(execSpy).toHaveBeenCalledWith(['logout', registry], {
expect(execSpy).toHaveBeenCalledWith(`docker`, ['logout', registry], {
ignoreReturnCode: true
});
});

65
__tests__/main.test.ts Normal file
View File

@ -0,0 +1,65 @@
import {expect, jest, test} from '@jest/globals';
import osm = require('os');
import {main} from '../src/main';
import * as docker from '../src/docker';
import * as stateHelper from '../src/state-helper';
test('errors without username and password', async () => {
jest.spyOn(osm, 'platform').mockImplementation(() => 'linux');
process.env['INPUT_LOGOUT'] = 'true'; // default value
await expect(main()).rejects.toThrow(new Error('Username and password required'));
});
test('successful with username and password', async () => {
jest.spyOn(osm, 'platform').mockImplementation(() => 'linux');
const setRegistrySpy = jest.spyOn(stateHelper, 'setRegistry');
const setLogoutSpy = jest.spyOn(stateHelper, 'setLogout');
const dockerSpy = jest.spyOn(docker, 'login').mockImplementation(() => Promise.resolve());
const username = 'dbowie';
process.env[`INPUT_USERNAME`] = username;
const password = 'groundcontrol';
process.env[`INPUT_PASSWORD`] = password;
const ecr = 'auto';
process.env['INPUT_ECR'] = ecr;
const logout = false;
process.env['INPUT_LOGOUT'] = String(logout);
await main();
expect(setRegistrySpy).toHaveBeenCalledWith('');
expect(setLogoutSpy).toHaveBeenCalledWith(logout);
expect(dockerSpy).toHaveBeenCalledWith('', username, password, ecr);
});
test('calls docker login', async () => {
jest.spyOn(osm, 'platform').mockImplementation(() => 'linux');
const setRegistrySpy = jest.spyOn(stateHelper, 'setRegistry');
const setLogoutSpy = jest.spyOn(stateHelper, 'setLogout');
const dockerSpy = jest.spyOn(docker, 'login').mockImplementation(() => Promise.resolve());
const username = 'dbowie';
process.env[`INPUT_USERNAME`] = username;
const password = 'groundcontrol';
process.env[`INPUT_PASSWORD`] = password;
const registry = 'ghcr.io';
process.env[`INPUT_REGISTRY`] = registry;
const ecr = 'auto';
process.env['INPUT_ECR'] = ecr;
const logout = true;
process.env['INPUT_LOGOUT'] = String(logout);
await main();
expect(setRegistrySpy).toHaveBeenCalledWith(registry);
expect(setLogoutSpy).toHaveBeenCalledWith(logout);
expect(dockerSpy).toHaveBeenCalledWith(registry, username, password, ecr);
});

View File

@ -26,6 +26,6 @@ inputs:
required: false
runs:
using: 'node20'
using: 'node16'
main: 'dist/index.js'
post: 'dist/index.js'

View File

@ -1,20 +1,15 @@
# syntax=docker/dockerfile:1
ARG NODE_VERSION=20
ARG NODE_VERSION=16
ARG DOCKER_VERSION=20.10.13
ARG BUILDX_VERSION=0.8.1
FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache cpio findutils git
WORKDIR /src
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache <<EOT
corepack enable
yarn --version
yarn config set --home enableTelemetry 0
EOT
FROM base AS deps
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn install && mkdir /vendor && cp yarn.lock /vendor
@ -27,7 +22,7 @@ RUN --mount=type=bind,target=.,rw <<EOT
git add -A
cp -rf /vendor/* .
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"'
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"'
git status --porcelain -- yarn.lock
exit 1
fi
@ -35,7 +30,6 @@ EOT
FROM deps AS build
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run build && mkdir /out && cp -Rf dist /out/
@ -56,27 +50,29 @@ EOT
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
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out
FROM scratch AS format-update
COPY --from=format /out /
FROM deps AS lint
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run lint
FROM docker:${DOCKER_VERSION} as docker
FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
FROM deps AS test
ENV RUNNER_TEMP=/tmp/github_runner
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run test --coverage --coverageDirectory=/tmp/coverage
--mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
--mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
yarn run test --coverageDirectory=/tmp/coverage
FROM scratch AS test-coverage
COPY --from=test /tmp/coverage /

118
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

18188
dist/licenses.txt generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ group "default" {
}
group "pre-checkin" {
targets = ["vendor", "format", "build"]
targets = ["vendor-update", "format", "build"]
}
group "validate" {
@ -34,7 +34,7 @@ target "lint" {
output = ["type=cacheonly"]
}
target "vendor" {
target "vendor-update" {
dockerfile = "dev.Dockerfile"
target = "vendor-update"
output = ["."]

View File

@ -15,7 +15,6 @@ process.env = Object.assign({}, process.env, {
module.exports = {
clearMocks: true,
testEnvironment: 'node',
moduleFileExtensions: ['js', 'ts'],
testMatch: ['**/*.test.ts'],
transform: {

View File

@ -1,16 +1,13 @@
{
"name": "docker-login",
"description": "GitHub Action to login against a Docker registry",
"main": "src/main.ts",
"main": "lib/main.js",
"scripts": {
"build": "ncc build --source-map --minify --license licenses.txt",
"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"
"build": "ncc build src/main.ts --source-map --minify --license licenses.txt",
"lint": "eslint src/**/*.ts __tests__/**/*.ts",
"format": "eslint --fix src/**/*.ts __tests__/**/*.ts",
"test": "jest --coverage",
"all": "yarn run build && yarn run format && yarn test"
},
"repository": {
"type": "git",
@ -21,30 +18,35 @@
"docker",
"login"
],
"author": "Docker Inc.",
"license": "Apache-2.0",
"packageManager": "yarn@3.6.3",
"author": "Docker",
"contributors": [
{
"name": "CrazyMax",
"url": "https://crazymax.dev"
}
],
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.1",
"@aws-sdk/client-ecr": "^3.583.0",
"@aws-sdk/client-ecr-public": "^3.583.0",
"@docker/actions-toolkit": "^0.35.0",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.5"
"@actions/core": "^1.10.0",
"@aws-sdk/client-ecr": "^3.347.1",
"@aws-sdk/client-ecr-public": "^3.347.1",
"@docker/actions-toolkit": "^0.2.0",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.0"
},
"devDependencies": {
"@types/node": "^20.12.12",
"@typescript-eslint/eslint-plugin": "^7.9.0",
"@typescript-eslint/parser": "^7.9.0",
"@vercel/ncc": "^0.38.1",
"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"
"@types/node": "^16.18.21",
"@typescript-eslint/eslint-plugin": "^5.56.0",
"@typescript-eslint/parser": "^5.56.0",
"@vercel/ncc": "^0.36.1",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.5.0",
"prettier": "^2.8.7",
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
}
}

View File

@ -1,7 +1,7 @@
import * as core from '@actions/core';
import {ECR} from '@aws-sdk/client-ecr';
import {ECRPUBLIC} from '@aws-sdk/client-ecr-public';
import {NodeHttpHandler} from '@smithy/node-http-handler';
import {NodeHttpHandler} from '@aws-sdk/node-http-handler';
import {HttpProxyAgent} from 'http-proxy-agent';
import {HttpsProxyAgent} from 'https-proxy-agent';

View File

@ -1,7 +1,6 @@
import * as aws from './aws';
import * as core from '@actions/core';
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
import {Exec} from '@docker/actions-toolkit/lib/exec';
export async function login(registry: string, username: string, password: string, ecr: string): Promise<void> {
if (/true/i.test(ecr) || (ecr == 'auto' && aws.isECR(registry))) {
@ -12,7 +11,7 @@ export async function login(registry: string, username: string, password: string
}
export async function logout(registry: string): Promise<void> {
await Docker.getExecOutput(['logout', registry], {
await Exec.getExecOutput('docker', ['logout', registry], {
ignoreReturnCode: true
}).then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
@ -22,15 +21,9 @@ export async function logout(registry: string): Promise<void> {
}
export async function loginStandard(registry: string, username: string, password: string): Promise<void> {
if (!username && !password) {
if (!username || !password) {
throw new Error('Username and password required');
}
if (!username) {
throw new Error('Username required');
}
if (!password) {
throw new Error('Password required');
}
const loginArgs: Array<string> = ['login', '--password-stdin'];
loginArgs.push('--username', username);
@ -41,7 +34,7 @@ export async function loginStandard(registry: string, username: string, password
} else {
core.info(`Logging into Docker Hub...`);
}
await Docker.getExecOutput(loginArgs, {
await Exec.getExecOutput('docker', loginArgs, {
ignoreReturnCode: true,
silent: true,
input: Buffer.from(password)
@ -58,7 +51,7 @@ export async function loginECR(registry: string, username: string, password: str
const regDatas = await aws.getRegistriesData(registry, username, password);
for (const regData of regDatas) {
core.info(`Logging into ${regData.registry}...`);
await Docker.getExecOutput(['login', '--password-stdin', '--username', regData.username, regData.registry], {
await Exec.getExecOutput('docker', ['login', '--password-stdin', '--username', regData.username, regData.registry], {
ignoreReturnCode: true,
silent: true,
input: Buffer.from(regData.password)

12350
yarn.lock

File diff suppressed because it is too large Load Diff