Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not sanitize before pattern matching #201

Merged
merged 2 commits into from May 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 24 additions & 7 deletions README.md
Expand Up @@ -31,6 +31,7 @@ ___
* [`type=raw`](#typeraw)
* [`type=sha`](#typesha)
* [Notes](#notes)
* [Image name and tag sanitization](#image-name-and-tag-sanitization)
* [Latest tag](#latest-tag)
* [Global expressions](#global-expressions)
* [`{{branch}}`](#branch)
Expand Down Expand Up @@ -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
a custom value through `value` attribute.

| Git tag | Pattern | Group | Output |
|-------------------------|-------------------------------|---------|------------------------|
| `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(\d.\d)` | `1` | `2.0` |
| `20200110-RC2` | `\d+` | `0` | `20200110` |
| `p1/v1.2.3` | `p1-v(\d.\d.\d)` | `1` | `1.2.3` |
| Git tag | Pattern | Group | Output |
|-------------------------|------------------|---------|------------------------|
| `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(\d.\d)` | `1` | `2.0` |
| `20200110-RC2` | `\d+` | `0` | `20200110` |
| `p1/v1.2.3` | `p1/v(\d.\d.\d)` | `1` | `1.2.3` |

Extended attributes and default values:

Expand Down Expand Up @@ -625,6 +626,22 @@ tags: |

## 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 is handled through the [`flavor` input](#flavor-input). It will be generated by default (`auto` mode) for:
Expand Down
4 changes: 2 additions & 2 deletions __tests__/image.test.ts
Expand Up @@ -53,7 +53,7 @@ describe('transform', () => {
[
`name=name/bar`,
`name/foo,enable=false`,
`name=ghcr.io/name/foo,enable=true`
`name=ghcr.io/UserName/Foo,enable=true`
],
[
{
Expand All @@ -65,7 +65,7 @@ describe('transform', () => {
enable: false,
},
{
name: `ghcr.io/name/foo`,
name: `ghcr.io/UserName/Foo`,
enable: true,
},
] as Image[],
Expand Down
10 changes: 5 additions & 5 deletions __tests__/meta.test.ts
Expand Up @@ -1277,9 +1277,9 @@ describe('tag', () => {
{
images: ['org/app', 'ghcr.io/user/app'],
tags: [
`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=3`,
`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=3`,
`type=ref,event=pr`,
`type=sha`
]
Expand Down Expand Up @@ -1316,8 +1316,8 @@ describe('tag', () => {
{
images: ['org/app', 'ghcr.io/user/app'],
tags: [
`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.\\d),group=1`,
`type=match,pattern=p1/v(\\d.\\d),group=1,suffix=`,
`type=ref,event=pr`,
`type=sha`
],
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/image.ts
Expand Up @@ -22,7 +22,7 @@ export function Transform(inputs: string[]): Image[] {
.split('=')
.map(item => item.trim());
if (parts.length == 1) {
images.push({name: parts[0].toLowerCase(), enable: true});
images.push({name: parts[0], enable: true});
} else {
newformat = true;
break;
Expand All @@ -46,13 +46,13 @@ export function Transform(inputs: string[]): Image[] {
.split('=')
.map(item => item.trim());
if (parts.length == 1) {
image.name = parts[0].toLowerCase();
image.name = parts[0];
} else {
const key = parts[0].toLowerCase();
const value = parts[1];
switch (key) {
case 'name': {
image.name = value.toLowerCase();
image.name = value;
break;
}
case 'enable': {
Expand Down
31 changes: 20 additions & 11 deletions src/meta.ts
Expand Up @@ -224,7 +224,7 @@ export class Meta {
if (tag.attrs['value'].length > 0) {
vraw = this.setGlobalExp(tag.attrs['value']);
} else {
vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-');
vraw = this.context.ref.replace(/^refs\/tags\//g, '');
}

let tmatch;
Expand All @@ -251,15 +251,15 @@ export class Meta {
if (!/^refs\/heads\//.test(this.context.ref)) {
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');
}

private procRefTag(version: Version, tag: tcl.Tag): Version {
if (!/^refs\/tags\//.test(this.context.ref)) {
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');
}

Expand All @@ -277,7 +277,7 @@ export class Meta {
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) {
tag.attrs['branch'] = this.repo.default_branch;
}
Expand Down Expand Up @@ -357,20 +357,20 @@ export class Meta {
if (!/^refs\/heads\//.test(ctx.ref)) {
return '';
}
return ctx.ref.replace(/^refs\/heads\//g, '').replace(/[^a-zA-Z0-9._-]+/g, '-');
return ctx.ref.replace(/^refs\/heads\//g, '');
},
tag: function () {
if (!/^refs\/tags\//.test(ctx.ref)) {
return '';
}
return ctx.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-');
return ctx.ref.replace(/^refs\/tags\//g, '');
},
sha: function () {
return ctx.sha.substr(0, 7);
},
base_ref: function () {
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
// to return the expected branch. See the comment below.
Expand Down Expand Up @@ -413,7 +413,7 @@ export class Meta {
if (!image.enable) {
continue;
}
images.push(image.name);
images.push(Meta.sanitizeImageName(image.name));
}
return images;
}
Expand All @@ -424,12 +424,13 @@ export class Meta {
}
const tags: Array<string> = [];
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) {
tags.push(`${imageName}:${partial}`);
tags.push(`${imageName}:${Meta.sanitizeTag(partial)}`);
}
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;
Expand Down Expand Up @@ -495,4 +496,12 @@ export class Meta {

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, '-');
}
}