Compare commits

...

8 Commits

Author SHA1 Message Date
CrazyMax
82a137ba99 documentation for scope input
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-01-08 12:16:46 +01:00
CrazyMax
6af99e858c chore: update generated content
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-01-08 12:16:45 +01:00
CrazyMax
3879c802e7 Add scope input to set scopes for the authentication token
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-01-08 12:12:52 +01:00
CrazyMax
916386b000 Merge pull request #911 from crazy-max/ensure-redact
ensure passwords are redacted with registry-auth
2026-01-07 09:35:51 +01:00
CrazyMax
5b3f94a294 chore: update generated content
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-01-06 11:21:53 +01:00
CrazyMax
f9cc43b63d ensure passwords are redacted with registry-auth
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-01-06 11:20:01 +01:00
CrazyMax
6862ffc5ab Merge pull request #902 from docker/dependabot/github_actions/actions/checkout-6
build(deps): bump actions/checkout from 5 to 6
2025-12-19 11:16:30 +01:00
dependabot[bot]
4349d75975 build(deps): bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [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/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-21 05:01:49 +00:00
14 changed files with 352 additions and 108 deletions

View File

@@ -19,7 +19,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Stop docker name: Stop docker
run: | run: |
@@ -43,7 +43,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to GitHub Container Registry name: Login to GitHub Container Registry
uses: ./ uses: ./
@@ -60,7 +60,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to GitHub Container Registry name: Login to GitHub Container Registry
uses: ./ uses: ./
@@ -85,7 +85,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to ACR name: Login to ACR
uses: ./ uses: ./
@@ -105,7 +105,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to Docker Hub name: Login to Docker Hub
uses: ./ uses: ./
@@ -124,7 +124,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to ECR name: Login to ECR
uses: ./ uses: ./
@@ -144,7 +144,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Configure AWS Credentials name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v5
@@ -169,7 +169,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to Public ECR name: Login to Public ECR
continue-on-error: ${{ matrix.os == 'windows-latest' }} continue-on-error: ${{ matrix.os == 'windows-latest' }}
@@ -192,7 +192,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Configure AWS Credentials name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v5
@@ -207,7 +207,7 @@ jobs:
with: with:
registry: public.ecr.aws registry: public.ecr.aws
github-container: ghcr:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
@@ -218,7 +218,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to GitHub Container Registry name: Login to GitHub Container Registry
uses: ./ uses: ./
@@ -238,7 +238,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to GitLab name: Login to GitLab
uses: ./ uses: ./
@@ -258,7 +258,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to Google Artifact Registry name: Login to Google Artifact Registry
uses: ./ uses: ./
@@ -278,7 +278,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to Google Container Registry name: Login to Google Container Registry
uses: ./ uses: ./
@@ -292,7 +292,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to registries name: Login to registries
uses: ./ uses: ./
@@ -315,7 +315,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to registries name: Login to registries
uses: ./ uses: ./
@@ -336,7 +336,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Login to registries name: Login to registries
id: login id: login
@@ -356,3 +356,125 @@ jobs:
echo "::error::Should have failed" echo "::error::Should have failed"
exit 1 exit 1
fi fi
scope-dockerhub:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Login to Docker Hub
uses: ./
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
scope: '@push'
-
name: Print config.json files
shell: bash
run: |
shopt -s globstar nullglob
for file in ~/.docker/**/config.json; do
echo "## ${file}"
jq '(.auths[]?.auth) |= "REDACTED"' "$file"
echo ""
done
scope-dockerhub-repo:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Login to Docker Hub
uses: ./
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
scope: 'docker/buildx-bin@push'
-
name: Print config.json files
shell: bash
run: |
shopt -s globstar nullglob
for file in ~/.docker/**/config.json; do
echo "## ${file}"
jq '(.auths[]?.auth) |= "REDACTED"' "$file"
echo ""
done
scope-ghcr:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Login to GitHub Container Registry
uses: ./
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
scope: '@push'
-
name: Print config.json files
shell: bash
run: |
shopt -s globstar nullglob
for file in ~/.docker/**/config.json; do
echo "## ${file}"
jq '(.auths[]?.auth) |= "REDACTED"' "$file"
echo ""
done
scope-ghcr-repo:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Login to GitHub Container Registry
uses: ./
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
scope: 'docker/login-action@push'
-
name: Print config.json files
shell: bash
run: |
shopt -s globstar nullglob
for file in ~/.docker/**/config.json; do
echo "## ${file}"
jq '(.auths[]?.auth) |= "REDACTED"' "$file"
echo ""
done

View File

@@ -31,7 +31,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Initialize CodeQL name: Initialize CodeQL
uses: github/codeql-action/init@v4 uses: github/codeql-action/init@v4

View File

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

View File

@@ -17,7 +17,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: Test name: Test
uses: docker/bake-action@v6 uses: docker/bake-action@v6

View File

@@ -19,7 +19,7 @@ jobs:
steps: steps:
- -
name: Checkout name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- -
name: List targets name: List targets
id: generate id: generate

View File

@@ -25,6 +25,7 @@ ___
* [Quay.io](#quayio) * [Quay.io](#quayio)
* [DigitalOcean](#digitalocean-container-registry) * [DigitalOcean](#digitalocean-container-registry)
* [Authenticate to multiple registries](#authenticate-to-multiple-registries) * [Authenticate to multiple registries](#authenticate-to-multiple-registries)
* [Set scopes for the authentication token](#set-scopes-for-the-authentication-token)
* [Customizing](#customizing) * [Customizing](#customizing)
* [inputs](#inputs) * [inputs](#inputs)
* [Contributing](#contributing) * [Contributing](#contributing)
@@ -527,8 +528,8 @@ jobs:
``` ```
You can also use the `registry-auth` input for raw authentication to You can also use the `registry-auth` input for raw authentication to
registries, defined as YAML objects. Each object can contain `registry`, registries, defined as YAML objects. Each object have the same attributes as
`username`, `password` and `ecr` keys similar to current inputs: current inputs (except `logout`):
> [!WARNING] > [!WARNING]
> We don't recommend using this method, it's better to use the action multiple > We don't recommend using this method, it's better to use the action multiple
@@ -557,6 +558,60 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
``` ```
### Set scopes for the authentication token
The `scope` input allows limiting registry credentials to a specific repository
or namespace scope when building images with Buildx.
This is useful in GitHub Actions to avoid overriding the Docker Hub
authentication token embedded in GitHub-hosted runners, which is used for
pulling images without rate limits. By scoping credentials, you can
authenticate only where needed (typically for pushing), while keeping
unauthenticated pulls for base images.
When `scope` is set, credentials are written to the Buildx configuration
instead of the global Docker configuration. This means:
* Authentication applies only to the specified scope
* The default Docker Hub credentials remain available for pulls
* Credentials are used only by Buildx during the build
> [!IMPORTANT]
> Credentials written to the Buildx configuration are only accessible by Buildx.
> They are not available to `docker pull`, `docker push`, or any other Docker
> CLI commands outside Buildx.
> [!NOTE]
> This feature requires Buildx version 0.31.0 or later.
```yaml
name: ci
on:
push:
branches: main
jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Login to Docker Hub (scoped)
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
scope: 'myorg/myimage@push'
-
name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: myorg/myimage:latest
```
In this example, base images are pulled using the embedded GitHub-hosted runner
credentials, while authenticated access is used only to push `myorg/myimage`.
## Customizing ## Customizing
### inputs ### inputs
@@ -568,13 +623,13 @@ The following inputs can be used as `step.with` keys:
| `registry` | String | `docker.io` | Server address of Docker registry. If not set then will default to Docker Hub | | `registry` | String | `docker.io` | Server address of Docker registry. If not set then will default to Docker Hub |
| `username` | String | | Username for authenticating to the Docker registry | | `username` | String | | Username for authenticating to the Docker registry |
| `password` | String | | Password or personal access token for authenticating the Docker registry | | `password` | String | | Password or personal access token for authenticating the Docker registry |
| `scope` | String | | Scope for the authentication token |
| `ecr` | String | `auto` | Specifies whether the given registry is ECR (`auto`, `true` or `false`) | | `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 | | `logout` | Bool | `true` | Log out from the Docker registry at the end of a job |
| `registry-auth` | YAML | | Raw authentication to registries, defined as YAML objects | | `registry-auth` | YAML | | Raw authentication to registries, defined as YAML objects |
> [!NOTE] > [!NOTE]
> The `registry-auth` input is mutually exclusive with `registry`, `username`, > The `registry-auth` input cannot be used with other inputs except `logout`.
> `password` and `ecr` inputs.
## Contributing ## Contributing

View File

@@ -50,7 +50,7 @@ test('logout calls exec', async () => {
const registry = 'https://ghcr.io'; const registry = 'https://ghcr.io';
await logout(registry); await logout(registry, '');
expect(execSpy).toHaveBeenCalledTimes(1); expect(execSpy).toHaveBeenCalledTimes(1);
const callfunc = execSpy.mock.calls[0]; const callfunc = execSpy.mock.calls[0];

View File

@@ -19,6 +19,9 @@ inputs:
ecr: ecr:
description: 'Specifies whether the given registry is ECR (auto, true or false)' description: 'Specifies whether the given registry is ECR (auto, true or false)'
required: false required: false
scope:
description: 'Scope for the authentication token'
required: false
logout: logout:
description: 'Log out from the Docker registry at the end of a job' description: 'Log out from the Docker registry at the end of a job'
default: 'true' default: 'true'

24
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

View File

@@ -1,21 +1,90 @@
import path from 'path';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as yaml from 'js-yaml';
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
import {Util} from '@docker/actions-toolkit/lib/util';
export interface Inputs { export interface Inputs {
registry: string; registry: string;
username: string; username: string;
password: string; password: string;
scope: string;
ecr: string; ecr: string;
logout: boolean; logout: boolean;
registryAuth: string; registryAuth: string;
} }
export interface Auth {
registry: string;
username: string;
password: string;
scope: string;
ecr: string;
configDir: string;
}
export function getInputs(): Inputs { export function getInputs(): Inputs {
return { return {
registry: core.getInput('registry'), registry: core.getInput('registry'),
username: core.getInput('username'), username: core.getInput('username'),
password: core.getInput('password'), password: core.getInput('password'),
scope: core.getInput('scope'),
ecr: core.getInput('ecr'), ecr: core.getInput('ecr'),
logout: core.getBooleanInput('logout'), logout: core.getBooleanInput('logout'),
registryAuth: core.getInput('registry-auth') registryAuth: core.getInput('registry-auth')
}; };
} }
export function getAuthList(inputs: Inputs): Array<Auth> {
if (inputs.registryAuth && (inputs.registry || inputs.username || inputs.password || inputs.scope || inputs.ecr)) {
throw new Error('Cannot use registry-auth with other inputs');
}
let auths: Array<Auth> = [];
if (!inputs.registryAuth) {
auths.push({
registry: inputs.registry || 'docker.io',
username: inputs.username,
password: inputs.password,
scope: inputs.scope,
ecr: inputs.ecr || 'auto',
configDir: scopeToConfigDir(inputs.registry, inputs.scope)
});
} else {
auths = (yaml.load(inputs.registryAuth) as Array<Auth>).map(auth => {
core.setSecret(auth.password); // redacted in workflow logs
return {
registry: auth.registry || 'docker.io',
username: auth.username,
password: auth.password,
scope: auth.scope,
ecr: auth.ecr || 'auto',
configDir: scopeToConfigDir(auth.registry || 'docker.io', auth.scope)
};
});
}
if (auths.length == 0) {
throw new Error('No registry to login');
}
return auths;
}
export function scopeToConfigDir(registry: string, scope?: string): string {
if (scopeDisabled() || !scope || scope === '') {
return '';
}
let configDir = path.join(Buildx.configDir, 'config', registry === 'docker.io' ? 'registry-1.docker.io' : registry);
if (scope.startsWith('@')) {
configDir += scope;
} else {
configDir = path.join(configDir, scope);
}
return configDir;
}
function scopeDisabled(): boolean {
if (process.env.DOCKER_LOGIN_SCOPE_DISABLED) {
return Util.parseBool(process.env.DOCKER_LOGIN_SCOPE_DISABLED);
}
return false;
}

View File

@@ -1,19 +1,31 @@
import * as aws from './aws';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as aws from './aws';
import * as context from './context';
import {Docker} from '@docker/actions-toolkit/lib/docker/docker'; import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
export async function login(registry: string, username: string, password: string, ecr: string): Promise<void> { export async function login(auth: context.Auth): Promise<void> {
if (/true/i.test(ecr) || (ecr == 'auto' && aws.isECR(registry))) { if (/true/i.test(auth.ecr) || (auth.ecr == 'auto' && aws.isECR(auth.registry))) {
await loginECR(registry, username, password); await loginECR(auth.registry, auth.username, auth.password, auth.scope);
} else { } else {
await loginStandard(registry, username, password); await loginStandard(auth.registry, auth.username, auth.password, auth.scope);
} }
} }
export async function logout(registry: string): Promise<void> { export async function logout(registry: string, configDir: string): Promise<void> {
let envs: {[key: string]: string} | undefined;
if (configDir !== '') {
envs = Object.assign({}, process.env, {
DOCKER_CONFIG: configDir
}) as {
[key: string]: string;
};
core.info(`Alternative config dir: ${configDir}`);
}
await Docker.getExecOutput(['logout', registry], { await Docker.getExecOutput(['logout', registry], {
ignoreReturnCode: true ignoreReturnCode: true,
env: envs
}).then(res => { }).then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) { if (res.stderr.length > 0 && res.exitCode != 0) {
core.warning(res.stderr.trim()); core.warning(res.stderr.trim());
@@ -21,7 +33,7 @@ export async function logout(registry: string): Promise<void> {
}); });
} }
export async function loginStandard(registry: string, username: string, password: string): Promise<void> { export async function loginStandard(registry: string, username: string, password: string, scope?: string): Promise<void> {
if (!username && !password) { if (!username && !password) {
throw new Error('Username and password required'); throw new Error('Username and password required');
} }
@@ -31,38 +43,39 @@ export async function loginStandard(registry: string, username: string, password
if (!password) { if (!password) {
throw new Error('Password required'); throw new Error('Password required');
} }
await loginExec(registry, username, password, scope);
}
const loginArgs: Array<string> = ['login', '--password-stdin']; export async function loginECR(registry: string, username: string, password: string, scope?: string): Promise<void> {
loginArgs.push('--username', username); core.info(`Retrieving registries data through AWS SDK...`);
loginArgs.push(registry); const regDatas = await aws.getRegistriesData(registry, username, password);
for (const regData of regDatas) {
await loginExec(regData.registry, regData.username, regData.password, scope);
}
}
core.info(`Logging into ${registry}...`); async function loginExec(registry: string, username: string, password: string, scope?: string): Promise<void> {
await Docker.getExecOutput(loginArgs, { let envs: {[key: string]: string} | undefined;
const configDir = context.scopeToConfigDir(registry, scope);
if (configDir !== '') {
envs = Object.assign({}, process.env, {
DOCKER_CONFIG: configDir
}) as {
[key: string]: string;
};
core.info(`Logging into ${registry} (scope ${scope})...`);
} else {
core.info(`Logging into ${registry}...`);
}
await Docker.getExecOutput(['login', '--password-stdin', '--username', username, registry], {
ignoreReturnCode: true, ignoreReturnCode: true,
silent: true, silent: true,
input: Buffer.from(password) input: Buffer.from(password),
env: envs
}).then(res => { }).then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) { if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(res.stderr.trim()); throw new Error(res.stderr.trim());
} }
core.info(`Login Succeeded!`); core.info('Login Succeeded!');
}); });
} }
export async function loginECR(registry: string, username: string, password: string): Promise<void> {
core.info(`Retrieving registries data through AWS SDK...`);
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], {
ignoreReturnCode: true,
silent: true,
input: Buffer.from(regData.password)
}).then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(res.stderr.trim());
}
core.info('Login Succeeded!');
});
}
}

View File

@@ -1,4 +1,3 @@
import * as yaml from 'js-yaml';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as actionsToolkit from '@docker/actions-toolkit'; import * as actionsToolkit from '@docker/actions-toolkit';
@@ -6,45 +5,21 @@ import * as context from './context';
import * as docker from './docker'; import * as docker from './docker';
import * as stateHelper from './state-helper'; import * as stateHelper from './state-helper';
interface Auth {
registry: string;
username: string;
password: string;
ecr: string;
}
export async function main(): Promise<void> { export async function main(): Promise<void> {
const inputs: context.Inputs = context.getInputs(); const inputs: context.Inputs = context.getInputs();
stateHelper.setLogout(inputs.logout); stateHelper.setLogout(inputs.logout);
if (inputs.registryAuth && (inputs.registry || inputs.username || inputs.password || inputs.ecr)) { const auths = context.getAuthList(inputs);
throw new Error('Cannot use registry-auth with other inputs'); stateHelper.setRegistries(Array.from(new Map(auths.map(auth => [`${auth.registry}|${auth.configDir}`, {registry: auth.registry, configDir: auth.configDir} as stateHelper.RegistryState])).values()));
}
if (!inputs.registryAuth) { if (auths.length === 1) {
stateHelper.setRegistries([inputs.registry || 'docker.io']); await docker.login(auths[0]);
await docker.login(inputs.registry || 'docker.io', inputs.username, inputs.password, inputs.ecr || 'auto');
return; return;
} }
const auths = yaml.load(inputs.registryAuth) as Auth[];
if (auths.length == 0) {
throw new Error('No registry to login');
}
const registries: string[] = [];
for (const auth of auths) { for (const auth of auths) {
if (!auth.registry) { await core.group(`Login to ${auth.registry}`, async () => {
registries.push('docker.io'); await docker.login(auth);
} else {
registries.push(auth.registry);
}
}
stateHelper.setRegistries(registries.filter((value, index, self) => self.indexOf(value) === index));
for (const auth of auths) {
await core.group(`Login to ${auth.registry || 'docker.io'}`, async () => {
await docker.login(auth.registry || 'docker.io', auth.username, auth.password, auth.ecr || 'auto');
}); });
} }
} }
@@ -53,8 +28,10 @@ async function post(): Promise<void> {
if (!stateHelper.logout) { if (!stateHelper.logout) {
return; return;
} }
for (const registry of stateHelper.registries.split(',')) { for (const registryState of stateHelper.registries) {
await docker.logout(registry); await core.group(`Logout from ${registryState.registry}`, async () => {
await docker.logout(registryState.registry, registryState.configDir);
});
} }
} }

View File

@@ -1,10 +1,15 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
export const registries = process.env['STATE_registries'] || ''; export const registries = process.env['STATE_registries'] ? (JSON.parse(process.env['STATE_registries']) as Array<RegistryState>) : [];
export const logout = /true/i.test(process.env['STATE_logout'] || ''); export const logout = /true/i.test(process.env['STATE_logout'] || '');
export function setRegistries(registries: string[]) { export interface RegistryState {
core.saveState('registries', registries.join(',')); registry: string;
configDir: string;
}
export function setRegistries(registries: Array<RegistryState>) {
core.saveState('registries', JSON.stringify(registries));
} }
export function setLogout(logout: boolean) { export function setLogout(logout: boolean) {