Merge pull request #887 from docker/multi-login

raw authentication to registries
This commit is contained in:
Tõnis Tiigi authored and GitHub committed 2025-09-12 10:09:37 -07:00
commit 65c0768122
11 files changed
+214 -25

No files matched your search

+70
View File
@@ -286,3 +286,73 @@ jobs:
registry: gcr.io
username: _json_key
password: ${{ secrets.GCR_JSON_KEY }}
registry-auth:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v5
-
name: Login to registries
uses: ./
with:
registry-auth: |
- username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- registry: public.ecr.aws
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- registry: registry.gitlab.com
username: ${{ secrets.GITLAB_USERNAME }}
password: ${{ secrets.GITLAB_TOKEN }}
registry-auth-dup:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v5
-
name: Login to registries
uses: ./
with:
registry-auth: |
- registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- registry: public.ecr.aws
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
registry-auth-exclusive:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v5
-
name: Login to registries
id: login
continue-on-error: true
uses: ./
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
registry-auth: |
- username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Check
run: |
if [ "${{ steps.login.outcome }}" != "failure" ] || [ "${{ steps.login.conclusion }}" != "success" ]; then
echo "::error::Should have failed"
exit 1
fi
+75 -7
View File
@@ -24,6 +24,7 @@ ___
* [OCI Oracle Cloud Infrastructure Registry (OCIR)](#oci-oracle-cloud-infrastructure-registry-ocir)
* [Quay.io](#quayio)
* [DigitalOcean](#digitalocean-container-registry)
* [Authenticate to multiple registries](#authenticate-to-multiple-registries)
* [Customizing](#customizing)
* [inputs](#inputs)
* [Contributing](#contributing)
@@ -494,19 +495,86 @@ jobs:
password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
```
### Authenticate to multiple registries
To authenticate against multiple registries, you can specify the login-action
step multiple times in your workflow:
```yaml
name: ci
on:
push:
branches: main
jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
```
You can also use the `registry-auth` input for raw authentication to
registries, defined as YAML objects. Each object can contain `registry`,
`username`, `password` and `ecr` keys similar to current inputs:
> [!WARNING]
> We don't recommend using this method, it's better to use the action multiple
> times as shown above.
```yaml
name: ci
on:
push:
branches: main
jobs:
login:
runs-on: ubuntu-latest
steps:
-
name: Login to registries
uses: docker/login-action@v3
with:
registry-auth: |
- username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
```
## Customizing
### inputs
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 |
| `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`) |
| `logout` | Bool | `true` | Log out from the Docker registry at the end of a job |
| Name | Type | Default | Description |
|-----------------|--------|-------------|-------------------------------------------------------------------------------|
| `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 |
| `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`) |
| `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 |
> [!NOTE]
> The `registry-auth` input is mutually exclusive with `registry`, `username`,
> `password` and `ecr` inputs.
## Contributing
+3 -1
View File
@@ -18,12 +18,14 @@ inputs:
required: false
ecr:
description: 'Specifies whether the given registry is ECR (auto, true or false)'
default: 'auto'
required: false
logout:
description: 'Log out from the Docker registry at the end of a job'
default: 'true'
required: false
registry-auth:
description: 'Raw authentication to registries, defined as YAML objects'
required: false
runs:
using: 'node20'
Generated Vendored
+1 -1
View File
@@ -103,5 +103,5 @@ const y=p(57147);const v=p(22037);const D=p(71017);const M=p(6113);const U={fs:y
* @license [MIT]{@link https://github.com/archiverjs/node-zip-stream/blob/master/LICENSE}
* @copyright (c) 2014 Chris Talkington, contributors.
*/
var y=p(73837).inherits;var v=p(25445).ZipArchiveOutputStream;var D=p(25445).ZipArchiveEntry;var M=p(82072);var U=i.exports=function(i){if(!(this instanceof U)){return new U(i)}i=this.options=i||{};i.zlib=i.zlib||{};v.call(this,i);if(typeof i.level==="number"&&i.level>=0){i.zlib.level=i.level;delete i.level}if(!i.forceZip64&&typeof i.zlib.level==="number"&&i.zlib.level===0){i.store=true}i.namePrependSlash=i.namePrependSlash||false;if(i.comment&&i.comment.length>0){this.setComment(i.comment)}};y(U,v);U.prototype._normalizeFileData=function(i){i=M.defaults(i,{type:"file",name:null,namePrependSlash:this.options.namePrependSlash,linkname:null,date:null,mode:null,store:this.options.store,comment:""});var d=i.type==="directory";var p=i.type==="symlink";if(i.name){i.name=M.sanitizePath(i.name);if(!p&&i.name.slice(-1)==="/"){d=true;i.type="directory"}else if(d){i.name+="/"}}if(d||p){i.store=true}i.date=M.dateify(i.date);return i};U.prototype.entry=function(i,d,p){if(typeof p!=="function"){p=this._emitErrorCallback.bind(this)}d=this._normalizeFileData(d);if(d.type!=="file"&&d.type!=="directory"&&d.type!=="symlink"){p(new Error(d.type+" entries not currently supported"));return}if(typeof d.name!=="string"||d.name.length===0){p(new Error("entry name must be a non-empty string value"));return}if(d.type==="symlink"&&typeof d.linkname!=="string"){p(new Error("entry linkname must be a non-empty string value when type equals symlink"));return}var y=new D(d.name);y.setTime(d.date,this.options.forceLocalTime);if(d.namePrependSlash){y.setName(d.name,true)}if(d.store){y.setMethod(0)}if(d.comment.length>0){y.setComment(d.comment)}if(d.type==="symlink"&&typeof d.mode!=="number"){d.mode=40960}if(typeof d.mode==="number"){if(d.type==="symlink"){d.mode|=40960}y.setUnixMode(d.mode)}if(d.type==="symlink"&&typeof d.linkname==="string"){i=Buffer.from(d.linkname)}return v.prototype.entry.call(this,y,i,p)};U.prototype.finalize=function(){this.finish()}},36949:function(i,d,p){"use strict";var y=this&&this.__createBinding||(Object.create?function(i,d,p,y){if(y===undefined)y=p;var v=Object.getOwnPropertyDescriptor(d,p);if(!v||("get"in v?!d.__esModule:v.writable||v.configurable)){v={enumerable:true,get:function(){return d[p]}}}Object.defineProperty(i,y,v)}:function(i,d,p,y){if(y===undefined)y=p;i[y]=d[p]});var v=this&&this.__setModuleDefault||(Object.create?function(i,d){Object.defineProperty(i,"default",{enumerable:true,value:d})}:function(i,d){i["default"]=d});var D=this&&this.__importStar||function(i){if(i&&i.__esModule)return i;var d={};if(i!=null)for(var p in i)if(p!=="default"&&Object.prototype.hasOwnProperty.call(i,p))y(d,i,p);v(d,i);return d};var M=this&&this.__awaiter||function(i,d,p,y){function adopt(i){return i instanceof p?i:new p((function(d){d(i)}))}return new(p||(p=Promise))((function(p,v){function fulfilled(i){try{step(y.next(i))}catch(i){v(i)}}function rejected(i){try{step(y["throw"](i))}catch(i){v(i)}}function step(i){i.done?p(i.value):adopt(i.value).then(fulfilled,rejected)}step((y=y.apply(i,d||[])).next())}))};Object.defineProperty(d,"__esModule",{value:true});d.getRegistriesData=d.getAccountIDs=d.getRegion=d.isPubECR=d.isECR=void 0;const U=D(p(42186));const V=p(8923);const j=p(42308);const K=p(20258);const ee=p(23764);const te=p(77219);const re=/^(([0-9]{12})\.(dkr\.ecr|dkr-ecr)\.(.+)\.(on\.aws|amazonaws\.com(.cn)?))(\/([^:]+)(:.+)?)?$/;const ne=/public\.ecr\.aws|ecr-public\.aws\.com/;const isECR=i=>re.test(i)||(0,d.isPubECR)(i);d.isECR=isECR;const isPubECR=i=>ne.test(i);d.isPubECR=isPubECR;const getRegion=i=>{if((0,d.isPubECR)(i)){return process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1"}const p=i.match(re);if(!p){return""}return p[4]};d.getRegion=getRegion;const getAccountIDs=i=>{if((0,d.isPubECR)(i)){return[]}const p=i.match(re);if(!p){return[]}const y=[p[2]];if(process.env.AWS_ACCOUNT_IDS){y.push(...process.env.AWS_ACCOUNT_IDS.split(","))}return y.filter(((i,d)=>y.indexOf(i)===d))};d.getAccountIDs=getAccountIDs;const getRegistriesData=(i,p,y)=>M(void 0,void 0,void 0,(function*(){const v=(0,d.getRegion)(i);const D=(0,d.getAccountIDs)(i);const M={};if(D.length>0){U.debug(`Requesting AWS ECR auth token for ${D.join(", ")}`);M["registryIds"]=D}let re;const ne=process.env.http_proxy||process.env.HTTP_PROXY||"";if(ne){U.debug(`Using http proxy ${ne}`);re=new ee.HttpProxyAgent(ne)}let se;const ie=process.env.https_proxy||process.env.HTTPS_PROXY||"";if(ie){U.debug(`Using https proxy ${ie}`);se=new te.HttpsProxyAgent(ie)}const oe=p&&y?{accessKeyId:p,secretAccessKey:y}:undefined;if((0,d.isPubECR)(i)){U.info(`AWS Public ECR detected with ${v} region`);const i=new j.ECRPUBLIC({customUserAgent:"docker-login-action",credentials:oe,region:v,requestHandler:new K.NodeHttpHandler({httpAgent:re,httpsAgent:se})});const d=yield i.getAuthorizationToken(M);if(!d.authorizationData||!d.authorizationData.authorizationToken){throw new Error("Could not retrieve an authorization token from AWS Public ECR")}const p=Buffer.from(dLine truncated
var y=p(73837).inherits;var v=p(25445).ZipArchiveOutputStream;var D=p(25445).ZipArchiveEntry;var M=p(82072);var U=i.exports=function(i){if(!(this instanceof U)){return new U(i)}i=this.options=i||{};i.zlib=i.zlib||{};v.call(this,i);if(typeof i.level==="number"&&i.level>=0){i.zlib.level=i.level;delete i.level}if(!i.forceZip64&&typeof i.zlib.level==="number"&&i.zlib.level===0){i.store=true}i.namePrependSlash=i.namePrependSlash||false;if(i.comment&&i.comment.length>0){this.setComment(i.comment)}};y(U,v);U.prototype._normalizeFileData=function(i){i=M.defaults(i,{type:"file",name:null,namePrependSlash:this.options.namePrependSlash,linkname:null,date:null,mode:null,store:this.options.store,comment:""});var d=i.type==="directory";var p=i.type==="symlink";if(i.name){i.name=M.sanitizePath(i.name);if(!p&&i.name.slice(-1)==="/"){d=true;i.type="directory"}else if(d){i.name+="/"}}if(d||p){i.store=true}i.date=M.dateify(i.date);return i};U.prototype.entry=function(i,d,p){if(typeof p!=="function"){p=this._emitErrorCallback.bind(this)}d=this._normalizeFileData(d);if(d.type!=="file"&&d.type!=="directory"&&d.type!=="symlink"){p(new Error(d.type+" entries not currently supported"));return}if(typeof d.name!=="string"||d.name.length===0){p(new Error("entry name must be a non-empty string value"));return}if(d.type==="symlink"&&typeof d.linkname!=="string"){p(new Error("entry linkname must be a non-empty string value when type equals symlink"));return}var y=new D(d.name);y.setTime(d.date,this.options.forceLocalTime);if(d.namePrependSlash){y.setName(d.name,true)}if(d.store){y.setMethod(0)}if(d.comment.length>0){y.setComment(d.comment)}if(d.type==="symlink"&&typeof d.mode!=="number"){d.mode=40960}if(typeof d.mode==="number"){if(d.type==="symlink"){d.mode|=40960}y.setUnixMode(d.mode)}if(d.type==="symlink"&&typeof d.linkname==="string"){i=Buffer.from(d.linkname)}return v.prototype.entry.call(this,y,i,p)};U.prototype.finalize=function(){this.finish()}},36949:function(i,d,p){"use strict";var y=this&&this.__createBinding||(Object.create?function(i,d,p,y){if(y===undefined)y=p;var v=Object.getOwnPropertyDescriptor(d,p);if(!v||("get"in v?!d.__esModule:v.writable||v.configurable)){v={enumerable:true,get:function(){return d[p]}}}Object.defineProperty(i,y,v)}:function(i,d,p,y){if(y===undefined)y=p;i[y]=d[p]});var v=this&&this.__setModuleDefault||(Object.create?function(i,d){Object.defineProperty(i,"default",{enumerable:true,value:d})}:function(i,d){i["default"]=d});var D=this&&this.__importStar||function(i){if(i&&i.__esModule)return i;var d={};if(i!=null)for(var p in i)if(p!=="default"&&Object.prototype.hasOwnProperty.call(i,p))y(d,i,p);v(d,i);return d};var M=this&&this.__awaiter||function(i,d,p,y){function adopt(i){return i instanceof p?i:new p((function(d){d(i)}))}return new(p||(p=Promise))((function(p,v){function fulfilled(i){try{step(y.next(i))}catch(i){v(i)}}function rejected(i){try{step(y["throw"](i))}catch(i){v(i)}}function step(i){i.done?p(i.value):adopt(i.value).then(fulfilled,rejected)}step((y=y.apply(i,d||[])).next())}))};Object.defineProperty(d,"__esModule",{value:true});d.getRegistriesData=d.getAccountIDs=d.getRegion=d.isPubECR=d.isECR=void 0;const U=D(p(42186));const V=p(8923);const j=p(42308);const K=p(20258);const ee=p(23764);const te=p(77219);const re=/^(([0-9]{12})\.(dkr\.ecr|dkr-ecr)\.(.+)\.(on\.aws|amazonaws\.com(.cn)?))(\/([^:]+)(:.+)?)?$/;const ne=/public\.ecr\.aws|ecr-public\.aws\.com/;const isECR=i=>re.test(i)||(0,d.isPubECR)(i);d.isECR=isECR;const isPubECR=i=>ne.test(i);d.isPubECR=isPubECR;const getRegion=i=>{if((0,d.isPubECR)(i)){return process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1"}const p=i.match(re);if(!p){return""}return p[4]};d.getRegion=getRegion;const getAccountIDs=i=>{if((0,d.isPubECR)(i)){return[]}const p=i.match(re);if(!p){return[]}const y=[p[2]];if(process.env.AWS_ACCOUNT_IDS){y.push(...process.env.AWS_ACCOUNT_IDS.split(","))}return y.filter(((i,d)=>y.indexOf(i)===d))};d.getAccountIDs=getAccountIDs;const getRegistriesData=(i,p,y)=>M(void 0,void 0,void 0,(function*(){const v=(0,d.getRegion)(i);const D=(0,d.getAccountIDs)(i);const M={};if(D.length>0){U.debug(`Requesting AWS ECR auth token for ${D.join(", ")}`);M["registryIds"]=D}let re;const ne=process.env.http_proxy||process.env.HTTP_PROXY||"";if(ne){U.debug(`Using http proxy ${ne}`);re=new ee.HttpProxyAgent(ne)}let se;const ie=process.env.https_proxy||process.env.HTTPS_PROXY||"";if(ie){U.debug(`Using https proxy ${ie}`);se=new te.HttpsProxyAgent(ie)}const oe=p&&y?{accessKeyId:p,secretAccessKey:y}:undefined;if((0,d.isPubECR)(i)){U.info(`AWS Public ECR detected with ${v} region`);const i=new j.ECRPUBLIC({customUserAgent:"docker-login-action",credentials:oe,region:v,requestHandler:new K.NodeHttpHandler({httpAgent:re,httpsAgent:se})});const d=yield i.getAuthorizationToken(M);if(!d.authorizationData||!d.authorizationData.authorizationToken){throw new Error("Could not retrieve an authorization token from AWS Public ECR")}const p=Buffer.from(dLine truncated
//# sourceMappingURL=index.js.map
Generated Vendored
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"index.js","names":["__createBinding","this","Object","create","o","m","k","k2","undefined","desc","getOwnPropertyDescriptor","__esModule","writable","configurable","enumerable","get","defineProperty","__exportStar","exports","p","prototype","hasOwnProperty","call","value","client_1","__webpack_require__","client","DefaultArtifactClient","Timestamp","runtime_1","runtime_2","runtime_3","runtime_4","runtime_5","runtime_6","runtime_7","Timestamp$Type","MessageType","constructor","super","no","name","kind","T","now","msg","ms","Date","seconds","PbLong","from","Math","floor","toString","nanos","toDate","message","toNumber","ceil","fromDate","date","getTime","internalJsonWrite","options","parse","Error","z","nanosStr","substring","toISOString","replace","internalJsonRead","json","target","typeofJsonValue","matches","match","Number","isNaN","globalThis","parseInt","repeat","length","MESSAGE_TYPE","reflectionMergePartial","internalBinaryRead","reader","end","pos","fieldNo","wireType","tag","int64","int32","u","readUnknownField","typeName","d","skip","UnknownFieldHandler","onRead","internalBinaryWrite","writer","WireType","Varint","writeUnknownFields","onWrite","BytesValue","StringValue","BoolValue","UInt32Value","Int32Value","UInt64Value","Int64Value","FloatValue","DoubleValue","DoubleValue$Type","refJsonWriter","scalar","refJsonReader","double","Bit64","FloatValue$Type","float","Bit32","Int64Value$Type","ScalarType","INT64","LongType","STRING","UInt64Value$Type","UINT64","uint64","Int32Value$Type","UInt32Value$Type","uint32","BoolValue$Type","bool","StringValue$Type","string","LengthDelimited","BytesValue$Type","Uint8Array","bytes","ArtifactService","DeleteArtifactResponse","DeleteArtifactRequest","GetSignedArtifactURLResponse","GetSignedArtifactURLRequest","ListArtifactsResponse_MonolithArtifact","ListArtifactsResponse","ListArtifactsRequest","FinalizeArtifactResponse","FinalizeArtifactRequest","CreateArtifactResponse","CreateArtifactRequest","FinalizeMigratedArtifactResponse","FinalizeMigratedArtifactRequest","MigrateArtifactResponse","MigrateArtifactRequest","runtime_rpc_1","wrappers_1","wrappers_2","timestamp_1","MigrateArtifactRequest$Type","workflowRunBackendId","expiresAt","fork","join","MigrateArtifactResponse$Type","ok","signedUploadUrl","FinalizeMigratedArtifactRequest$Type","size","FinalizeMigratedArtifactResponse$Type","artifactId","CreateArtifactRequest$Type","workflowJobRunBackendId","version","CreateArtifactResponse$Type","FinalizeArtifactRequest$Type","hash","FinalizeArtifactResponse$Type","ListArtifactsRequest$Type","nameFilter","idFilter","ListArtifactsResponse$Type","artifacts","push","i","ListArtifactsResponse_MonolithArtifact$Type","databaseId","createdAt","digest","GetSignedArtifactURLRequest$Type","GetSignedArtifactURLResponse$Type","signedUrl","DeleteArtifactRequest$Type","DeleteArtifactResponse$Type","ServiceType","I","O","ArtifactServiceClientProtobuf","ArtifactServiceClientJSON","artifact_1","rpc","CreateArtifact","bind","FinalizeArtifact","ListArtifacts","GetSignedArtifactURL","DeleteArtifact","request","data","toJson","useProtoFieldName","emitDefaultValues","promise","then","fromJson","ignoreUnknownFields","toBinary","fromBinary","__awaiter","thisArg","_arguments","P","generator","adopt","resolve","Promise","reject","fulfilled","step","next","e","rejected","result","done","apply","__rest","s","t","indexOf","getOwnPropertySymbols","propertyIsEnumerable","core_1","config_1","upload_artifact_1","download_artifact_1","delete_artifact_1","get_artifact_1","list_artifacts_1","errors_1","uploadArtifact","files","rootDirectory","isGhes","GHESNotSupportedError","error","warning","downloadArtifact","findBy","repositoryOwner","repositoryName","token","downloadOptions","downloadArtifactPublic","downloadArtifactInternal","listArtifacts","workflowRunId","listArtifactsPublic","latest","listArtifactsInternal","getArtifact","artifactName","getArtifactPublic","getArtifactInternal","deleteArtifact","deleteArtifactPublic","deleteArtifactInternal","github_1","user_agent_1","retry_options_1","utils_1","plugin_request_log_1","plugin_retry_1","artifact_twirp_client_1","util_1","generated_1","_a","retryOpts","requestOpts","getRetryOptions","defaults","opts","log","userAgent","getUserAgentString","previews","retry","github","getOctokit","requestLog","getArtifactResp","deleteArtifactResp","rest","actions","owner","repo","artifact_id","artifact","id","status","InvalidResponseError","headers","artifactClient","internalArtifactTwirpClient","getBackendIdsFromToken","listReq","listRes","ArtifactNotFoundError","sort","a","b","debug","req","res","info","__setModuleDefault","v","__importStar","mod","__importDefault","default","streamExtractExternal","promises_1","crypto","stream","core","httpClient","unzip_stream_1","scrubQueryParameters","url","parsed","URL","search","exists","path","access","code","streamExtract","directory","retryCount","setTimeout","HttpClient","response","statusCode","statusMessLine truncated
{"version":3,"file":"index.js","names":["__createBinding","this","Object","create","o","m","k","k2","undefined","desc","getOwnPropertyDescriptor","__esModule","writable","configurable","enumerable","get","defineProperty","__exportStar","exports","p","prototype","hasOwnProperty","call","value","client_1","__webpack_require__","client","DefaultArtifactClient","Timestamp","runtime_1","runtime_2","runtime_3","runtime_4","runtime_5","runtime_6","runtime_7","Timestamp$Type","MessageType","constructor","super","no","name","kind","T","now","msg","ms","Date","seconds","PbLong","from","Math","floor","toString","nanos","toDate","message","toNumber","ceil","fromDate","date","getTime","internalJsonWrite","options","parse","Error","z","nanosStr","substring","toISOString","replace","internalJsonRead","json","target","typeofJsonValue","matches","match","Number","isNaN","globalThis","parseInt","repeat","length","MESSAGE_TYPE","reflectionMergePartial","internalBinaryRead","reader","end","pos","fieldNo","wireType","tag","int64","int32","u","readUnknownField","typeName","d","skip","UnknownFieldHandler","onRead","internalBinaryWrite","writer","WireType","Varint","writeUnknownFields","onWrite","BytesValue","StringValue","BoolValue","UInt32Value","Int32Value","UInt64Value","Int64Value","FloatValue","DoubleValue","DoubleValue$Type","refJsonWriter","scalar","refJsonReader","double","Bit64","FloatValue$Type","float","Bit32","Int64Value$Type","ScalarType","INT64","LongType","STRING","UInt64Value$Type","UINT64","uint64","Int32Value$Type","UInt32Value$Type","uint32","BoolValue$Type","bool","StringValue$Type","string","LengthDelimited","BytesValue$Type","Uint8Array","bytes","ArtifactService","DeleteArtifactResponse","DeleteArtifactRequest","GetSignedArtifactURLResponse","GetSignedArtifactURLRequest","ListArtifactsResponse_MonolithArtifact","ListArtifactsResponse","ListArtifactsRequest","FinalizeArtifactResponse","FinalizeArtifactRequest","CreateArtifactResponse","CreateArtifactRequest","FinalizeMigratedArtifactResponse","FinalizeMigratedArtifactRequest","MigrateArtifactResponse","MigrateArtifactRequest","runtime_rpc_1","wrappers_1","wrappers_2","timestamp_1","MigrateArtifactRequest$Type","workflowRunBackendId","expiresAt","fork","join","MigrateArtifactResponse$Type","ok","signedUploadUrl","FinalizeMigratedArtifactRequest$Type","size","FinalizeMigratedArtifactResponse$Type","artifactId","CreateArtifactRequest$Type","workflowJobRunBackendId","version","CreateArtifactResponse$Type","FinalizeArtifactRequest$Type","hash","FinalizeArtifactResponse$Type","ListArtifactsRequest$Type","nameFilter","idFilter","ListArtifactsResponse$Type","artifacts","push","i","ListArtifactsResponse_MonolithArtifact$Type","databaseId","createdAt","digest","GetSignedArtifactURLRequest$Type","GetSignedArtifactURLResponse$Type","signedUrl","DeleteArtifactRequest$Type","DeleteArtifactResponse$Type","ServiceType","I","O","ArtifactServiceClientProtobuf","ArtifactServiceClientJSON","artifact_1","rpc","CreateArtifact","bind","FinalizeArtifact","ListArtifacts","GetSignedArtifactURL","DeleteArtifact","request","data","toJson","useProtoFieldName","emitDefaultValues","promise","then","fromJson","ignoreUnknownFields","toBinary","fromBinary","__awaiter","thisArg","_arguments","P","generator","adopt","resolve","Promise","reject","fulfilled","step","next","e","rejected","result","done","apply","__rest","s","t","indexOf","getOwnPropertySymbols","propertyIsEnumerable","core_1","config_1","upload_artifact_1","download_artifact_1","delete_artifact_1","get_artifact_1","list_artifacts_1","errors_1","uploadArtifact","files","rootDirectory","isGhes","GHESNotSupportedError","error","warning","downloadArtifact","findBy","repositoryOwner","repositoryName","token","downloadOptions","downloadArtifactPublic","downloadArtifactInternal","listArtifacts","workflowRunId","listArtifactsPublic","latest","listArtifactsInternal","getArtifact","artifactName","getArtifactPublic","getArtifactInternal","deleteArtifact","deleteArtifactPublic","deleteArtifactInternal","github_1","user_agent_1","retry_options_1","utils_1","plugin_request_log_1","plugin_retry_1","artifact_twirp_client_1","util_1","generated_1","_a","retryOpts","requestOpts","getRetryOptions","defaults","opts","log","userAgent","getUserAgentString","previews","retry","github","getOctokit","requestLog","getArtifactResp","deleteArtifactResp","rest","actions","owner","repo","artifact_id","artifact","id","status","InvalidResponseError","headers","artifactClient","internalArtifactTwirpClient","getBackendIdsFromToken","listReq","listRes","ArtifactNotFoundError","sort","a","b","debug","req","res","info","__setModuleDefault","v","__importStar","mod","__importDefault","default","streamExtractExternal","promises_1","crypto","stream","core","httpClient","unzip_stream_1","scrubQueryParameters","url","parsed","URL","search","exists","path","access","code","streamExtract","directory","retryCount","setTimeout","HttpClient","response","statusCode","statusMessLine truncated
+3 -1
View File
@@ -30,9 +30,11 @@
"@aws-sdk/client-ecr-public": "^3.859.0",
"@docker/actions-toolkit": "^0.62.1",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.6"
"https-proxy-agent": "^7.0.6",
"js-yaml": "^4.1.0"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.12.12",
"@typescript-eslint/eslint-plugin": "^7.9.0",
"@typescript-eslint/parser": "^7.9.0",
+3 -1
View File
@@ -6,6 +6,7 @@ export interface Inputs {
password: string;
ecr: string;
logout: boolean;
registryAuth: string;
}
export function getInputs(): Inputs {
@@ -14,6 +15,7 @@ export function getInputs(): Inputs {
username: core.getInput('username'),
password: core.getInput('password'),
ecr: core.getInput('ecr'),
logout: core.getBooleanInput('logout')
logout: core.getBooleanInput('logout'),
registryAuth: core.getInput('registry-auth')
};
}
+1 -5
View File
@@ -36,11 +36,7 @@ export async function loginStandard(registry: string, username: string, password
loginArgs.push('--username', username);
loginArgs.push(registry);
if (registry) {
core.info(`Logging into ${registry}...`);
} else {
core.info(`Logging into Docker Hub...`);
}
core.info(`Logging into ${registry}...`);
await Docker.getExecOutput(loginArgs, {
ignoreReturnCode: true,
silent: true,
+45 -5
View File
@@ -1,21 +1,61 @@
import * as yaml from 'js-yaml';
import * as core from '@actions/core';
import * as actionsToolkit from '@docker/actions-toolkit';
import * as context from './context';
import * as docker from './docker';
import * as stateHelper from './state-helper';
interface Auth {
registry: string;
username: string;
password: string;
ecr: string;
}
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);
const inputs: context.Inputs = context.getInputs();
stateHelper.setLogout(inputs.logout);
if (inputs.registryAuth && (inputs.registry || inputs.username || inputs.password || inputs.ecr)) {
throw new Error('Cannot use registry-auth with other inputs');
}
if (!inputs.registryAuth) {
stateHelper.setRegistries([inputs.registry || 'docker.io']);
await docker.login(inputs.registry || 'docker.io', inputs.username, inputs.password, inputs.ecr || 'auto');
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) {
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) {
await core.group(`Login to ${auth.registry || 'docker.io'}`, async () => {
await docker.login(auth.registry || 'docker.io', auth.username, auth.password, auth.ecr || 'auto');
});
}
}
async function post(): Promise<void> {
if (!stateHelper.logout) {
return;
}
await docker.logout(stateHelper.registry);
for (const registry of stateHelper.registries.split(',')) {
await docker.logout(registry);
}
}
actionsToolkit.run(main, post);
+3 -3
View File
@@ -1,10 +1,10 @@
import * as core from '@actions/core';
export const registry = process.env['STATE_registry'] || '';
export const registries = process.env['STATE_registries'] || '';
export const logout = /true/i.test(process.env['STATE_logout'] || '');
export function setRegistry(registry: string) {
core.saveState('registry', registry);
export function setRegistries(registries: string[]) {
core.saveState('registries', registries.join(','));
}
export function setLogout(logout: boolean) {
+9
View File
@@ -3236,6 +3236,13 @@ __metadata:
languageName: node
linkType: hard
"@types/js-yaml@npm:^4.0.9":
version: 4.0.9
resolution: "@types/js-yaml@npm:4.0.9"
checksum: e5e5e49b5789a29fdb1f7d204f82de11cb9e8f6cb24ab064c616da5d6e1b3ccfbf95aa5d1498a9fbd3b9e745564e69b4a20b6c530b5a8bbb2d4eb830cda9bc69
languageName: node
linkType: hard
"@types/node-fetch@npm:^2.5.0":
version: 2.6.4
resolution: "@types/node-fetch@npm:2.6.4"
@@ -4315,6 +4322,7 @@ __metadata:
"@aws-sdk/client-ecr": ^3.859.0
"@aws-sdk/client-ecr-public": ^3.859.0
"@docker/actions-toolkit": ^0.62.1
"@types/js-yaml": ^4.0.9
"@types/node": ^20.12.12
"@typescript-eslint/eslint-plugin": ^7.9.0
"@typescript-eslint/parser": ^7.9.0
@@ -4326,6 +4334,7 @@ __metadata:
http-proxy-agent: ^7.0.2
https-proxy-agent: ^7.0.6
jest: ^29.7.0
js-yaml: ^4.1.0
prettier: ^3.2.5
ts-jest: ^29.1.2
ts-node: ^10.9.2