mirror of
https://github.com/docker/login-action.git
synced 2026-04-06 23:08:18 +01:00
Compare commits
2 Commits
dependabot
...
20e0a61734
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20e0a61734 | ||
|
|
f40589c4bf |
124
.github/workflows/ci.yml
vendored
124
.github/workflows/ci.yml
vendored
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -568,13 +568,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
|
||||||
|
|
||||||
|
|||||||
@@ -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
24
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -4,6 +4,7 @@ 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;
|
||||||
@@ -14,6 +15,7 @@ export function getInputs(): Inputs {
|
|||||||
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')
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
|
import path from 'path';
|
||||||
import * as aws from './aws';
|
import * as aws from './aws';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
||||||
|
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
|
||||||
|
|
||||||
export async function login(registry: string, username: string, password: string, ecr: string): Promise<void> {
|
export interface Auth {
|
||||||
if (/true/i.test(ecr) || (ecr == 'auto' && aws.isECR(registry))) {
|
registry: string;
|
||||||
await loginECR(registry, username, password);
|
username: string;
|
||||||
|
password: string;
|
||||||
|
scope?: string;
|
||||||
|
ecr: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function login(auth: 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 {
|
} else {
|
||||||
await loginStandard(registry, username, password);
|
await loginStandard(auth.registry, auth.username, auth.password, auth.scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +31,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 +41,44 @@ 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;
|
||||||
|
if (scope && scope.length > 0) {
|
||||||
|
let dockerConfigDir = path.join(Buildx.configDir, 'config', registry === 'docker.io' ? 'registry-1.docker.io' : registry);
|
||||||
|
if (scope.startsWith('@')) {
|
||||||
|
dockerConfigDir += scope;
|
||||||
|
} else {
|
||||||
|
dockerConfigDir = path.join(dockerConfigDir, scope);
|
||||||
|
}
|
||||||
|
envs = Object.assign({}, process.env, {
|
||||||
|
DOCKER_CONFIG: dockerConfigDir
|
||||||
|
}) as {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
core.info(`Logging into ${registry} with 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!');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
39
src/main.ts
39
src/main.ts
@@ -6,45 +6,42 @@ 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)) {
|
if (inputs.registryAuth && (inputs.registry || inputs.username || inputs.password || inputs.scope || inputs.ecr)) {
|
||||||
throw new Error('Cannot use registry-auth with other inputs');
|
throw new Error('Cannot use registry-auth with other inputs');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inputs.registryAuth) {
|
if (!inputs.registryAuth) {
|
||||||
stateHelper.setRegistries([inputs.registry || 'docker.io']);
|
stateHelper.setRegistries([inputs.registry || 'docker.io']);
|
||||||
await docker.login(inputs.registry || 'docker.io', inputs.username, inputs.password, inputs.ecr || 'auto');
|
await docker.login({
|
||||||
|
registry: inputs.registry || 'docker.io',
|
||||||
|
username: inputs.username,
|
||||||
|
password: inputs.password,
|
||||||
|
scope: inputs.scope,
|
||||||
|
ecr: inputs.ecr || 'auto'
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auths = yaml.load(inputs.registryAuth) as Auth[];
|
const auths = (yaml.load(inputs.registryAuth) as docker.Auth[]).map(auth => ({
|
||||||
|
registry: auth.registry || 'docker.io',
|
||||||
|
username: auth.username,
|
||||||
|
password: auth.password,
|
||||||
|
scope: auth.scope,
|
||||||
|
ecr: auth.ecr || 'auto'
|
||||||
|
}));
|
||||||
if (auths.length == 0) {
|
if (auths.length == 0) {
|
||||||
throw new Error('No registry to login');
|
throw new Error('No registry to login');
|
||||||
}
|
}
|
||||||
|
|
||||||
const registries: string[] = [];
|
stateHelper.setRegistries(auths.map(auth => auth.registry).filter((value, index, self) => self.indexOf(value) === index));
|
||||||
for (const auth of auths) {
|
|
||||||
if (!auth.registry) {
|
|
||||||
registries.push('docker.io');
|
|
||||||
} else {
|
|
||||||
registries.push(auth.registry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateHelper.setRegistries(registries.filter((value, index, self) => self.indexOf(value) === index));
|
|
||||||
|
|
||||||
for (const auth of auths) {
|
for (const auth of auths) {
|
||||||
await core.group(`Login to ${auth.registry || 'docker.io'}`, async () => {
|
await core.group(`Login to ${auth.registry}`, async () => {
|
||||||
await docker.login(auth.registry || 'docker.io', auth.username, auth.password, auth.ecr || 'auto');
|
await docker.login(auth);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user