mirror of
https://gitea.com/docker/metadata-action.git
synced 2024-11-29 07:29:32 +01:00
Merge pull request #201 from crazy-max/fix-sanitization
Do not sanitize before pattern matching
This commit is contained in:
commit
26b9439ce3
7 changed files with 56 additions and 30 deletions
21
README.md
21
README.md
|
@ -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)
|
||||||
|
@ -509,12 +510,12 @@ Can create a regular expression for matching Git tag with a pattern and capturin
|
||||||
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:
|
||||||
|
|
|
@ -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[],
|
||||||
|
|
|
@ -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`
|
||||||
],
|
],
|
||||||
|
|
2
dist/index.js
generated
vendored
2
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
|
@ -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': {
|
||||||
|
|
31
src/meta.ts
31
src/meta.ts
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -357,20 +357,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 +413,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;
|
||||||
}
|
}
|
||||||
|
@ -424,12 +424,13 @@ export class Meta {
|
||||||
}
|
}
|
||||||
const tags: Array<string> = [];
|
const tags: Array<string> = [];
|
||||||
for (const imageName of this.getImageNames()) {
|
for (const imageName of this.getImageNames()) {
|
||||||
tags.push(`${imageName}:${this.version.main}`);
|
tags.push(`${imageName}:${Meta.sanitizeTag(this.version.main)}`);
|
||||||
for (const partial of this.version.partial) {
|
for (const partial of this.version.partial) {
|
||||||
tags.push(`${imageName}:${partial}`);
|
tags.push(`${imageName}:${Meta.sanitizeTag(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 +496,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, '-');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue