diff --git a/.github/docker-login.png b/.github/docker-login.png index 580bc18..b6ef963 100644 Binary files a/.github/docker-login.png and b/.github/docker-login.png differ diff --git a/README.md b/README.md index bcd41b1..d86c59b 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ ___ * [GitLab](#gitlab) * [Azure Container Registry (ACR)](#azure-container-registry-acr) * [Google Container Registry (GCR)](#google-container-registry-gcr) + * [Google Artifact Registry (GAR)](#google-artifact-registry-gar) * [AWS Elastic Container Registry (ECR)](#aws-elastic-container-registry-ecr) * [Customizing](#customizing) * [inputs](#inputs) @@ -162,6 +163,11 @@ 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) +> to learn about transitioning to Google Artifact Registry. + 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) @@ -187,6 +193,36 @@ jobs: password: ${{ secrets.GCR_JSON_KEY }} ``` +### Google Artifact Registry (GAR) + +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`. + +```yaml +name: ci + +on: + push: + branches: master + +jobs: + login: + runs-on: ubuntu-latest + steps: + - + name: Login to GAR + uses: docker/login-action@v1 + with: + registry: -docker.pkg.dev + username: _json_key + password: ${{ secrets.GAR_JSON_KEY }} +``` + +> Replace `` 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. + ### AWS Elastic Container Registry (ECR) Use an IAM user with the [ability to push to ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html). @@ -213,6 +249,34 @@ jobs: password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} ``` +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 + +on: + push: + branches: master + +jobs: + login: + runs-on: ubuntu-latest + steps: + - + name: Configure AWS Credentials + 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: + - + name: Login to ECR + uses: docker/login-action@v1 + with: + registry: .dkr.ecr..amazonaws.com +``` + > Replace `` and `` with their respective values. ## Customizing diff --git a/__tests__/context.test.ts b/__tests__/context.test.ts index 886619b..bd6abe6 100644 --- a/__tests__/context.test.ts +++ b/__tests__/context.test.ts @@ -2,20 +2,7 @@ import osm = require('os'); import {getInputs} from '../src/context'; -test('without username getInputs throws errors', async () => { - expect(() => { - getInputs(); - }).toThrowError('Input required and not supplied: username'); -}); - -test('without password getInputs throws errors', async () => { - process.env['INPUT_USERNAME'] = 'dbowie'; - expect(() => { - getInputs(); - }).toThrowError('Input required and not supplied: password'); -}); - -test('with password and username getInputs does not error', async () => { +test('with password and username getInputs does not throw error', async () => { process.env['INPUT_USERNAME'] = 'dbowie'; process.env['INPUT_PASSWORD'] = 'groundcontrol'; expect(() => { diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 062c7c2..7c8782e 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -17,7 +17,7 @@ test('errors when not run on linux platform', async () => { expect(coreSpy).toHaveBeenCalledWith('Only supported on linux platform'); }); -test('errors without username', async () => { +test('errors without username and password', async () => { const platSpy = jest.spyOn(osm, 'platform'); platSpy.mockImplementation(() => 'linux'); @@ -25,21 +25,7 @@ test('errors without username', async () => { await run(); - expect(coreSpy).toHaveBeenCalledWith('Input required and not supplied: username'); -}); - -test('errors without password', async () => { - const platSpy = jest.spyOn(osm, 'platform'); - platSpy.mockImplementation(() => 'linux'); - - const coreSpy: jest.SpyInstance = jest.spyOn(core, 'setFailed'); - - const username: string = 'dbowie'; - process.env[`INPUT_USERNAME`] = username; - - await run(); - - expect(coreSpy).toHaveBeenCalledWith('Input required and not supplied: password'); + expect(coreSpy).toHaveBeenCalledWith('Username and password required'); }); test('successful with username and password', async () => { @@ -79,7 +65,7 @@ test('calls docker login', async () => { const password: string = 'groundcontrol'; process.env[`INPUT_PASSWORD`] = password; - const registry: string = 'https://ghcr.io'; + const registry: string = 'ghcr.io'; process.env[`INPUT_REGISTRY`] = registry; const logout: string = 'true'; diff --git a/action.yml b/action.yml index 3766856..039e609 100644 --- a/action.yml +++ b/action.yml @@ -12,10 +12,10 @@ inputs: required: false username: description: 'Username used to log against the Docker registry' - required: true + required: false password: description: 'Password or personal access token used to log against the Docker registry' - required: true + required: false logout: description: 'Log out from the Docker registry at the end of a job' default: 'true' diff --git a/dist/index.js b/dist/index.js index aec5702..8d45f5a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3062,10 +3062,11 @@ function logout(registry) { exports.logout = logout; function loginStandard(registry, username, password) { return __awaiter(this, void 0, void 0, function* () { - let loginArgs = ['login', '--password-stdin']; - if (username) { - loginArgs.push('--username', username); + if (!username || !password) { + throw new Error('Username and password required'); } + let loginArgs = ['login', '--password-stdin']; + loginArgs.push('--username', username); loginArgs.push(registry); if (registry) { core.info(`🔑 Logging into ${registry}...`); @@ -3088,8 +3089,8 @@ function loginECR(registry, username, password) { const cliVersion = yield aws.getCLIVersion(); const region = yield aws.getRegion(registry); core.info(`💡 AWS ECR detected with ${region} region`); - process.env.AWS_ACCESS_KEY_ID = username; - process.env.AWS_SECRET_ACCESS_KEY = password; + process.env.AWS_ACCESS_KEY_ID = username || process.env.AWS_ACCESS_KEY_ID; + process.env.AWS_SECRET_ACCESS_KEY = password || process.env.AWS_SECRET_ACCESS_KEY; core.info(`⬇️ Retrieving docker login command through AWS CLI ${cliVersion} (${cliPath})...`); const loginCmd = yield aws.getDockerLoginCmd(cliVersion, registry, region); core.info(`🔑 Logging into ${registry}...`); @@ -3647,8 +3648,8 @@ const core = __importStar(__webpack_require__(186)); function getInputs() { return { registry: core.getInput('registry'), - username: core.getInput('username', { required: true }), - password: core.getInput('password', { required: true }), + username: core.getInput('username'), + password: core.getInput('password'), logout: core.getInput('logout') }; } diff --git a/src/context.ts b/src/context.ts index 953ea21..9074f5c 100644 --- a/src/context.ts +++ b/src/context.ts @@ -10,8 +10,8 @@ export interface Inputs { export function getInputs(): Inputs { return { registry: core.getInput('registry'), - username: core.getInput('username', {required: true}), - password: core.getInput('password', {required: true}), + username: core.getInput('username'), + password: core.getInput('password'), logout: core.getInput('logout') }; } diff --git a/src/docker.ts b/src/docker.ts index 369666f..a5de9ea 100644 --- a/src/docker.ts +++ b/src/docker.ts @@ -19,10 +19,12 @@ export async function logout(registry: string): Promise { } export async function loginStandard(registry: string, username: string, password: string): Promise { - let loginArgs: Array = ['login', '--password-stdin']; - if (username) { - loginArgs.push('--username', username); + if (!username || !password) { + throw new Error('Username and password required'); } + + let loginArgs: Array = ['login', '--password-stdin']; + loginArgs.push('--username', username); loginArgs.push(registry); if (registry) { @@ -44,8 +46,8 @@ export async function loginECR(registry: string, username: string, password: str const region = await aws.getRegion(registry); core.info(`💡 AWS ECR detected with ${region} region`); - process.env.AWS_ACCESS_KEY_ID = username; - process.env.AWS_SECRET_ACCESS_KEY = password; + process.env.AWS_ACCESS_KEY_ID = username || process.env.AWS_ACCESS_KEY_ID; + process.env.AWS_SECRET_ACCESS_KEY = password || process.env.AWS_SECRET_ACCESS_KEY; core.info(`⬇️ Retrieving docker login command through AWS CLI ${cliVersion} (${cliPath})...`); const loginCmd = await aws.getDockerLoginCmd(cliVersion, registry, region);