first commit
This commit is contained in:
commit
8d4c98a481
18
action.yaml
Normal file
18
action.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
name: Docker Tag
|
||||
description: Tags an existing container manifest in a remote registry without pulling/pushing any images
|
||||
runs:
|
||||
using: node16
|
||||
main: main.js
|
||||
inputs:
|
||||
registry:
|
||||
description: URL to the container registry
|
||||
required: true
|
||||
image:
|
||||
description: The name of the image in the registry
|
||||
required: true
|
||||
old-tag:
|
||||
description: The tag of the existing image to be re-tagged
|
||||
required: true
|
||||
new-tags:
|
||||
description: Newline delimited list of new tags to apply to the image
|
||||
required: true
|
116
main.js
Normal file
116
main.js
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
const core = require('@actions/core');
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
|
||||
main();
|
||||
|
||||
const manifest_media_type = 'application/vnd.docker.distribution.manifest.v2+json';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const input = {
|
||||
registry: core.getInput('registry'),
|
||||
image: core.getInput('image'),
|
||||
old_tag: core.getInput('old-tag'),
|
||||
new_tags: core.getInput('new-tags').trim().split('\n'),
|
||||
};
|
||||
|
||||
const manifest = await get_manifest(`${input.registry}/v2/${input.image}/manifests/${input.old_tag}`);
|
||||
const promises = input.new_tags.map((new_tag) => {
|
||||
return put_manifest(`${input.registry}/v2/${input.image}/manifests/${new_tag}`, manifest);
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function get_manifest(url_str) {
|
||||
const { status, body: existing_manifest } = await http_req('GET', url_str, {
|
||||
accept: manifest_media_type,
|
||||
});
|
||||
|
||||
if (status !== 200) {
|
||||
throw new Error('failed to fetch existing manifest');
|
||||
}
|
||||
|
||||
return existing_manifest;
|
||||
}
|
||||
|
||||
async function put_manifest(url_str, manifest) {
|
||||
const { status } = await http_req('PUT', url_str, {
|
||||
'content-type': manifest_media_type,
|
||||
}, manifest);
|
||||
|
||||
if (status >= 400) {
|
||||
throw new Error('failed to put manifest');
|
||||
}
|
||||
}
|
||||
|
||||
async function http_req(method, url_str, headers, body) {
|
||||
const url = new URL(url_str);
|
||||
const make_request
|
||||
= url.protocol === 'https:' ? https.request
|
||||
: url.protocol === 'http:' ? http.request
|
||||
: null;
|
||||
|
||||
if (! make_request) {
|
||||
throw new Error('registry URL protocol not http(s)');
|
||||
}
|
||||
|
||||
if (url.username || url.password) {
|
||||
throw new Error('urls containing user credentials not allowed');
|
||||
}
|
||||
|
||||
const result = {
|
||||
url,
|
||||
status: null,
|
||||
body: null,
|
||||
headers: null,
|
||||
};
|
||||
|
||||
const path = url.pathname + (url.search || '');
|
||||
const port = url.port ? parseInt(url.port, 10) : (url.protocol === 'https:' ? 443 : 80);
|
||||
|
||||
return new Promise<HttpResult>((resolve, reject) => {
|
||||
const req = make_request({
|
||||
method: method,
|
||||
protocol: url.protocol,
|
||||
hostname: url.hostname,
|
||||
port: port,
|
||||
path: path,
|
||||
headers: headers
|
||||
}, (res) => {
|
||||
result.status = res.statusCode;
|
||||
result.body = '';
|
||||
|
||||
res.on('data', (chunk) => {
|
||||
result.body += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
result.headers = res.headers;
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
|
||||
req.setTimeout(timeout, () => {
|
||||
req.destroy();
|
||||
reject(new Error('request timeout'));
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
if (body) {
|
||||
req.write(body);
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
25
readme.md
Normal file
25
readme.md
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Action for re-tagging an existing docker multi-arch manifest
|
||||
|
||||
## Inputs
|
||||
|
||||
<!-- -->
|
||||
|
||||
## Example usage
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Tag the "gitea.example.com/owner/package:latest" image with some new tags
|
||||
uses: https://gitea.jbrumond.me/actions/docker-tag@v0.1
|
||||
with:
|
||||
registry: https://gitea.example.com
|
||||
image: owner/package
|
||||
old-tag: latest
|
||||
new-tags: |
|
||||
tag1
|
||||
tag2
|
||||
tag3
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user