Compare commits

...

9 Commits
v3 ... v4.0.1

Author SHA1 Message Date
CrazyMax
69f6fc9d46 Merge pull request #203 from crazy-max/san-fix
Sanitize tag earlier
2022-05-05 13:57:05 +02:00
CrazyMax
2f5b5ae8bf Sanitize tag earlier
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2022-05-05 13:54:54 +02:00
CrazyMax
f206c36955 Merge pull request #202 from crazy-max/v4-prep
readme: set metadata-action to v4
2022-05-05 11:43:25 +02:00
CrazyMax
a20adfa74e readme: set metadata-action to v4
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2022-05-05 11:41:40 +02:00
CrazyMax
26b9439ce3 Merge pull request #201 from crazy-max/fix-sanitization
Do not sanitize before pattern matching
2022-05-05 11:33:19 +02:00
CrazyMax
467883f452 Merge pull request #176 from crazy-max/node-16
Node 16 as default runtime
2022-05-05 11:32:46 +02:00
CrazyMax
5edf56f2c4 Node 16 as default runtime
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2022-05-04 15:14:01 +02:00
CrazyMax
678218f2be Note about image name and tag sanitization
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2022-05-04 15:02:47 +02:00
CrazyMax
e44c1fbe6e Do not sanitize before pattern matching
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2022-05-04 15:02:20 +02:00
10 changed files with 65 additions and 38 deletions

View File

@@ -31,6 +31,7 @@ ___
* [`type=raw`](#typeraw) * [`type=raw`](#typeraw)
* [`type=sha`](#typesha) * [`type=sha`](#typesha)
* [Notes](#notes) * [Notes](#notes)
* [Image name and tag sanitization](#image-name-and-tag-sanitization)
* [Latest tag](#latest-tag) * [Latest tag](#latest-tag)
* [Global expressions](#global-expressions) * [Global expressions](#global-expressions)
* [`{{branch}}`](#branch) * [`{{branch}}`](#branch)
@@ -71,7 +72,7 @@ jobs:
- -
name: Docker meta name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v4
with: with:
images: name/app images: name/app
- -
@@ -124,7 +125,7 @@ jobs:
- -
name: Docker meta name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v4
with: with:
images: | images: |
name/app name/app
@@ -202,7 +203,7 @@ jobs:
- -
name: Docker meta name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v4
with: with:
images: | images: |
name/app name/app
@@ -508,13 +509,13 @@ Can create a regular expression for matching Git tag with a pattern and capturin
[push tag event](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push) but, you can also use [push tag event](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push) but, you can also use
a custom value through `value` attribute. a custom value through `value` attribute.
| Git tag | Pattern | Group | Output | | Git tag | Pattern | Group | Output |
|-------------------------|-------------------------------|---------|------------------------| |-------------------------|------------------|---------|------------------------|
| `v1.2.3` | `\d.\d.\d` | `0` | `1.2.3` | | `v1.2.3` | `\d.\d.\d` | `0` | `1.2.3` |
| `v2.0.8-beta.67` | `v(.*)` | `1` | `2.0.8-beta.67` | | `v2.0.8-beta.67` | `v(.*)` | `1` | `2.0.8-beta.67` |
| `v2.0.8-beta.67` | `v(\d.\d)` | `1` | `2.0` | | `v2.0.8-beta.67` | `v(\d.\d)` | `1` | `2.0` |
| `20200110-RC2` | `\d+` | `0` | `20200110` | | `20200110-RC2` | `\d+` | `0` | `20200110` |
| `p1/v1.2.3` | `p1-v(\d.\d.\d)` | `1` | `1.2.3` | | `p1/v1.2.3` | `p1/v(\d.\d.\d)` | `1` | `1.2.3` |
Extended attributes and default values: Extended attributes and default values:
@@ -625,6 +626,22 @@ tags: |
## Notes ## Notes
### Image name and tag sanitization
In order to comply with [the specification](https://docs.docker.com/engine/reference/commandline/tag/#extended-description),
the image name components may contain lowercase letters, digits and separators.
A separator is defined as a period, one or two underscores, or one or more
dashes. A name component may not start or end with a separator.
A tag name must be a valid ASCII chars sequences and may contain lowercase and
uppercase letters, digits, underscores, periods and dashes. A tag name may not
start with a period or a dash and may contain a maximum of 128 characters.
To ease the integration in your workflow, this action will automatically:
* Lowercase the image name
* Replace invalid chars sequences with `-` for tags
### Latest tag ### Latest tag
`latest` tag is handled through the [`flavor` input](#flavor-input). It will be generated by default (`auto` mode) for: `latest` tag is handled through the [`flavor` input](#flavor-input). It will be generated by default (`auto` mode) for:
@@ -750,7 +767,7 @@ workflow using the [`fromJSON` function](https://docs.github.com/en/actions/lear
```yaml ```yaml
- -
name: Docker meta name: Docker meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v4
id: meta id: meta
with: with:
images: name/app images: name/app
@@ -775,7 +792,7 @@ labels generated are not suitable, you can overwrite them like this:
- -
name: Docker meta name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v4
with: with:
images: name/app images: name/app
labels: | labels: |

View File

@@ -2,7 +2,7 @@
## v2 to v3 ## v2 to v3
* Repository has been moved to docker org. Replace `crazy-max/ghaction-docker-meta@v2` with `docker/metadata-action@v3` * Repository has been moved to docker org. Replace `crazy-max/ghaction-docker-meta@v2` with `docker/metadata-action@v4`
* The default bake target has been changed: `ghaction-docker-meta` > `docker-metadata-action` * The default bake target has been changed: `ghaction-docker-meta` > `docker-metadata-action`
## v1 to v2 ## v1 to v2
@@ -180,7 +180,7 @@ jobs:
- -
name: Docker meta name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v4
with: with:
images: name/app images: name/app
- -
@@ -273,7 +273,7 @@ jobs:
- -
name: Docker meta name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v4
with: with:
images: name/app images: name/app
tags: | tags: |

View File

@@ -53,7 +53,7 @@ describe('transform', () => {
[ [
`name=name/bar`, `name=name/bar`,
`name/foo,enable=false`, `name/foo,enable=false`,
`name=ghcr.io/name/foo,enable=true` `name=ghcr.io/UserName/Foo,enable=true`
], ],
[ [
{ {
@@ -65,7 +65,7 @@ describe('transform', () => {
enable: false, enable: false,
}, },
{ {
name: `ghcr.io/name/foo`, name: `ghcr.io/UserName/Foo`,
enable: true, enable: true,
}, },
] as Image[], ] as Image[],

View File

@@ -1277,9 +1277,9 @@ describe('tag', () => {
{ {
images: ['org/app', 'ghcr.io/user/app'], images: ['org/app', 'ghcr.io/user/app'],
tags: [ tags: [
`type=match,pattern=p1-v(\\d.\\d.\\d),group=1`, `type=match,pattern=p1/v(\\d.\\d.\\d),group=1`,
`type=match,pattern=p1-v(\\d.\\d),group=1`, `type=match,pattern=p1/v(\\d.\\d),group=1`,
`type=match,pattern=p1-v(\\d.\\d),group=3`, `type=match,pattern=p1/v(\\d.\\d),group=3`,
`type=ref,event=pr`, `type=ref,event=pr`,
`type=sha` `type=sha`
] ]
@@ -1316,8 +1316,8 @@ describe('tag', () => {
{ {
images: ['org/app', 'ghcr.io/user/app'], images: ['org/app', 'ghcr.io/user/app'],
tags: [ tags: [
`type=match,pattern=p1-v(\\d.\\d.\\d),group=1`, `type=match,pattern=p1/v(\\d.\\d.\\d),group=1`,
`type=match,pattern=p1-v(\\d.\\d),group=1,suffix=`, `type=match,pattern=p1/v(\\d.\\d),group=1,suffix=`,
`type=ref,event=pr`, `type=ref,event=pr`,
`type=sha` `type=sha`
], ],

View File

@@ -46,5 +46,5 @@ outputs:
description: 'JSON output of tags and labels' description: 'JSON output of tags and labels'
runs: runs:
using: 'node12' using: 'node16'
main: 'dist/index.js' main: 'dist/index.js'

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG NODE_VERSION=12 ARG NODE_VERSION=16
FROM node:${NODE_VERSION}-alpine AS base FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache cpio findutils git RUN apk add --no-cache cpio findutils git

2
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View File

@@ -22,7 +22,7 @@ export function Transform(inputs: string[]): Image[] {
.split('=') .split('=')
.map(item => item.trim()); .map(item => item.trim());
if (parts.length == 1) { if (parts.length == 1) {
images.push({name: parts[0].toLowerCase(), enable: true}); images.push({name: parts[0], enable: true});
} else { } else {
newformat = true; newformat = true;
break; break;
@@ -46,13 +46,13 @@ export function Transform(inputs: string[]): Image[] {
.split('=') .split('=')
.map(item => item.trim()); .map(item => item.trim());
if (parts.length == 1) { if (parts.length == 1) {
image.name = parts[0].toLowerCase(); image.name = parts[0];
} else { } else {
const key = parts[0].toLowerCase(); const key = parts[0].toLowerCase();
const value = parts[1]; const value = parts[1];
switch (key) { switch (key) {
case 'name': { case 'name': {
image.name = value.toLowerCase(); image.name = value;
break; break;
} }
case 'enable': { case 'enable': {

View File

@@ -224,7 +224,7 @@ export class Meta {
if (tag.attrs['value'].length > 0) { if (tag.attrs['value'].length > 0) {
vraw = this.setGlobalExp(tag.attrs['value']); vraw = this.setGlobalExp(tag.attrs['value']);
} else { } else {
vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-'); vraw = this.context.ref.replace(/^refs\/tags\//g, '');
} }
let tmatch; let tmatch;
@@ -251,7 +251,7 @@ export class Meta {
if (!/^refs\/heads\//.test(this.context.ref)) { if (!/^refs\/heads\//.test(this.context.ref)) {
return version; return version;
} }
const vraw = this.setValue(this.context.ref.replace(/^refs\/heads\//g, '').replace(/[^a-zA-Z0-9._-]+/g, '-'), tag); const vraw = this.setValue(this.context.ref.replace(/^refs\/heads\//g, ''), tag);
return Meta.setVersion(version, vraw, this.flavor.latest == 'auto' ? false : this.flavor.latest == 'true'); return Meta.setVersion(version, vraw, this.flavor.latest == 'auto' ? false : this.flavor.latest == 'true');
} }
@@ -259,7 +259,7 @@ export class Meta {
if (!/^refs\/tags\//.test(this.context.ref)) { if (!/^refs\/tags\//.test(this.context.ref)) {
return version; return version;
} }
const vraw = this.setValue(this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-'), tag); const vraw = this.setValue(this.context.ref.replace(/^refs\/tags\//g, ''), tag);
return Meta.setVersion(version, vraw, this.flavor.latest == 'auto' ? true : this.flavor.latest == 'true'); return Meta.setVersion(version, vraw, this.flavor.latest == 'auto' ? true : this.flavor.latest == 'true');
} }
@@ -277,7 +277,7 @@ export class Meta {
return version; return version;
} }
const val = this.context.ref.replace(/^refs\/heads\//g, '').replace(/[^a-zA-Z0-9._-]+/g, '-'); const val = this.context.ref.replace(/^refs\/heads\//g, '');
if (tag.attrs['branch'].length == 0) { if (tag.attrs['branch'].length == 0) {
tag.attrs['branch'] = this.repo.default_branch; tag.attrs['branch'] = this.repo.default_branch;
} }
@@ -312,6 +312,7 @@ export class Meta {
if (val.length == 0) { if (val.length == 0) {
return version; return version;
} }
val = Meta.sanitizeTag(val);
if (version.main == undefined) { if (version.main == undefined) {
version.main = val; version.main = val;
} else if (val !== version.main) { } else if (val !== version.main) {
@@ -357,20 +358,20 @@ export class Meta {
if (!/^refs\/heads\//.test(ctx.ref)) { if (!/^refs\/heads\//.test(ctx.ref)) {
return ''; return '';
} }
return ctx.ref.replace(/^refs\/heads\//g, '').replace(/[^a-zA-Z0-9._-]+/g, '-'); return ctx.ref.replace(/^refs\/heads\//g, '');
}, },
tag: function () { tag: function () {
if (!/^refs\/tags\//.test(ctx.ref)) { if (!/^refs\/tags\//.test(ctx.ref)) {
return ''; return '';
} }
return ctx.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-'); return ctx.ref.replace(/^refs\/tags\//g, '');
}, },
sha: function () { sha: function () {
return ctx.sha.substr(0, 7); return ctx.sha.substr(0, 7);
}, },
base_ref: function () { base_ref: function () {
if (/^refs\/tags\//.test(ctx.ref) && ctx.payload?.base_ref != undefined) { if (/^refs\/tags\//.test(ctx.ref) && ctx.payload?.base_ref != undefined) {
return ctx.payload.base_ref.replace(/^refs\/heads\//g, '').replace(/\//g, '-'); return ctx.payload.base_ref.replace(/^refs\/heads\//g, '');
} }
// FIXME: keep this for backward compatibility even if doesn't always seem // FIXME: keep this for backward compatibility even if doesn't always seem
// to return the expected branch. See the comment below. // to return the expected branch. See the comment below.
@@ -413,7 +414,7 @@ export class Meta {
if (!image.enable) { if (!image.enable) {
continue; continue;
} }
images.push(image.name); images.push(Meta.sanitizeImageName(image.name));
} }
return images; return images;
} }
@@ -429,7 +430,8 @@ export class Meta {
tags.push(`${imageName}:${partial}`); tags.push(`${imageName}:${partial}`);
} }
if (this.version.latest) { if (this.version.latest) {
tags.push(`${imageName}:${this.flavor.prefixLatest ? this.flavor.prefix : ''}latest${this.flavor.suffixLatest ? this.flavor.suffix : ''}`); const latestTag = `${this.flavor.prefixLatest ? this.flavor.prefix : ''}latest${this.flavor.suffixLatest ? this.flavor.suffix : ''}`;
tags.push(`${imageName}:${Meta.sanitizeTag(latestTag)}`);
} }
} }
return tags; return tags;
@@ -495,4 +497,12 @@ export class Meta {
return bakeFile; return bakeFile;
} }
private static sanitizeImageName(name: string): string {
return name.toLowerCase();
}
private static sanitizeTag(tag: string): string {
return tag.replace(/[^a-zA-Z0-9._-]+/g, '-');
}
} }