Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ ___
* [OCI Oracle Cloud Infrastructure Registry (OCIR)](#oci-oracle-cloud-infrastructure-registry-ocir)
* [Quay.io](#quayio)
* [DigitalOcean](#digitalocean-container-registry)
* [Multiple Registries](#multiple-registries)
* [Customizing](#customizing)
* [inputs](#inputs)
* [Contributing](#contributing)
Expand Down Expand Up @@ -494,6 +495,34 @@ jobs:
password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
```

### Multiple Registries
You can login to multiple registries by providing a multiline string for the registry input. Each registry will be processed sequentically using the same username and password.

```yaml
name: ci

on:
push:
branches: main

jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Login to Multiple Regsitries
uses: docker/login-action@v7
with:
registry: |
ghcr.io
docker.io
registry.gitlab.com
# for single registry,
# registry: "ghcr.io"
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
```

## Customizing

### inputs
Expand All @@ -502,7 +531,7 @@ The 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 |
| `registry` | String | | Server address of Docker registry. If not set then will default to Docker Hub. Supports multiline string for multiplr registries. |
| `username` | String | | Username for authenticating to the Docker registry |
| `password` | String | | Password or personal access token for authenticating the Docker registry |
| `ecr` | String | `auto` | Specifies whether the given registry is ECR (`auto`, `true` or `false`) |
Expand Down
60 changes: 46 additions & 14 deletions __tests__/docker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,34 @@ test('loginStandard calls exec', async () => {

const username = 'dbowie';
const password = 'groundcontrol';
const registry = 'https://ghcr.io';
// Define const registry as multiline input
const registry = `https://ghcr.io
https://docker.io`;

await loginStandard(registry, username, password);
const registryArray = registry.split('\n').map(r => r.trim());

expect(execSpy).toHaveBeenCalledTimes(1);
const callfunc = execSpy.mock.calls[0];
if (callfunc && callfunc[1]) {
for (const reg of registryArray) {
await loginStandard(reg, username, password);
}

expect(execSpy).toHaveBeenCalledTimes(2);
const firstcall = execSpy.mock.calls[0];
if (firstcall && firstcall[1]) {
// we don't want to check env opt
firstcall[1].env = undefined;
}
expect(execSpy).toHaveBeenCalledWith(['login', '--password-stdin', '--username', username, registryArray[0]], {
input: Buffer.from(password),
silent: true,
ignoreReturnCode: true
});

const secondcall = execSpy.mock.calls[1];
if (secondcall && secondcall[1]) {
// we don't want to check env opt
callfunc[1].env = undefined;
secondcall[1].env = undefined;
}
expect(execSpy).toHaveBeenCalledWith(['login', '--password-stdin', '--username', username, registry], {
expect(execSpy).toHaveBeenCalledWith(['login', '--password-stdin', '--username', username, registryArray[1]], {
input: Buffer.from(password),
silent: true,
ignoreReturnCode: true
Expand All @@ -48,17 +65,32 @@ test('logout calls exec', async () => {
};
});

const registry = 'https://ghcr.io';
const registry = `https://ghcr.io
https://docker.io`;

await logout(registry);
const registryArray = registry.split('\n').map(r => r.trim());

expect(execSpy).toHaveBeenCalledTimes(1);
const callfunc = execSpy.mock.calls[0];
if (callfunc && callfunc[1]) {
for (const reg of registryArray) {
await logout(reg);
}

expect(execSpy).toHaveBeenCalledTimes(2);
const firstcall = execSpy.mock.calls[0];
if (firstcall && firstcall[1]) {
// we don't want to check env opt
firstcall[1].env = undefined;
}
expect(execSpy).toHaveBeenCalledWith(['logout', registryArray[0]], {
ignoreReturnCode: true
});

const secondcall = execSpy.mock.calls[1];
if (secondcall && secondcall[1]) {
// we don't want to check env opt
callfunc[1].env = undefined;
secondcall[1].env = undefined;
}
expect(execSpy).toHaveBeenCalledWith(['logout', registry], {

expect(execSpy).toHaveBeenCalledWith(['logout', registryArray[1]], {
ignoreReturnCode: true
});
});
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}
}
4 changes: 2 additions & 2 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as core from '@actions/core';

export interface Inputs {
registry: string;
registry: string[];
username: string;
password: string;
ecr: string;
Expand All @@ -10,7 +10,7 @@ export interface Inputs {

export function getInputs(): Inputs {
return {
registry: core.getInput('registry'),
registry: core.getMultilineInput('registry'),
username: core.getInput('username'),
password: core.getInput('password'),
ecr: core.getInput('ecr'),
Expand Down
11 changes: 8 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import * as context from './context';
import * as docker from './docker';
import * as stateHelper from './state-helper';

const input: context.Inputs = context.getInputs();

export async function main(): Promise<void> {
const input: context.Inputs = context.getInputs();
stateHelper.setRegistry(input.registry);
stateHelper.setLogout(input.logout);
await docker.login(input.registry, input.username, input.password, input.ecr);
for (const reg of input.registry) {
await docker.login(reg, input.username, input.password, input.ecr);
}
}

async function post(): Promise<void> {
if (!stateHelper.logout) {
return;
}
await docker.logout(stateHelper.registry);
for (const reg of input.registry) {
await docker.logout(reg);
}
}

actionsToolkit.run(main, post);
5 changes: 3 additions & 2 deletions src/state-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import * as core from '@actions/core';
export const registry = process.env['STATE_registry'] || '';
export const logout = /true/i.test(process.env['STATE_logout'] || '');

export function setRegistry(registry: string) {
core.saveState('registry', registry);
export function setRegistry(registry: string[]) {
core.info(`Setting registry: ${registry.join(',')}`);
core.saveState('registry', registry.join(','));
}

export function setLogout(logout: boolean) {
Expand Down