Allow global prefix/suffix on latest

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2021-07-05 20:37:02 +02:00
parent aa7478bca1
commit 375e313280
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
7 changed files with 245 additions and 59 deletions

View File

@ -296,8 +296,8 @@ flavor: |
``` ```
* `latest=<auto|true|false>`: Handle [latest tag](#latest-tag) (default `auto`) * `latest=<auto|true|false>`: Handle [latest tag](#latest-tag) (default `auto`)
* `prefix=<string>`: A global prefix for each generated tag * `prefix=<string>,onlatest=<true|false>`: A global prefix for each generated tag and optionnally for `latest`
* `suffix=<string>`: A global suffix for each generated tag * `suffix=<string>,onlatest=<true|false>`: A global suffix for each generated tag and optionnally for `latest`
## `tags` input ## `tags` input

View File

@ -32,7 +32,9 @@ describe('transform', () => {
{ {
latest: "true", latest: "true",
prefix: "", prefix: "",
suffix: "" prefixLatest: false,
suffix: "",
suffixLatest: false,
} as Flavor, } as Flavor,
false false
], ],
@ -43,7 +45,9 @@ describe('transform', () => {
{ {
latest: "false", latest: "false",
prefix: "", prefix: "",
suffix: "" prefixLatest: false,
suffix: "",
suffixLatest: false,
} as Flavor, } as Flavor,
false false
], ],
@ -54,7 +58,9 @@ describe('transform', () => {
{ {
latest: "auto", latest: "auto",
prefix: "", prefix: "",
suffix: "" prefixLatest: false,
suffix: "",
suffixLatest: false,
} as Flavor, } as Flavor,
false false
], ],
@ -72,7 +78,9 @@ describe('transform', () => {
{ {
latest: "auto", latest: "auto",
prefix: "sha-", prefix: "sha-",
suffix: "" prefixLatest: false,
suffix: "",
suffixLatest: false,
} as Flavor, } as Flavor,
false false
], ],
@ -83,7 +91,9 @@ describe('transform', () => {
{ {
latest: "auto", latest: "auto",
prefix: "", prefix: "",
suffix: "-alpine" prefixLatest: false,
suffix: "-alpine",
suffixLatest: false,
} as Flavor, } as Flavor,
false false
], ],
@ -96,7 +106,49 @@ describe('transform', () => {
{ {
latest: "false", latest: "false",
prefix: "dev-", prefix: "dev-",
suffix: "-alpine" prefixLatest: false,
suffix: "-alpine",
suffixLatest: false,
} as Flavor,
false
],
[
[
`prefix=dev-,onlatest=true`,
],
{
latest: "auto",
prefix: "dev-",
prefixLatest: true,
suffix: "",
suffixLatest: false,
} as Flavor,
false
],
[
[
`suffix=-alpine,onlatest=true`,
],
{
latest: "auto",
prefix: "",
prefixLatest: false,
suffix: "-alpine",
suffixLatest: true,
} as Flavor,
false
],
[
[
`prefix=dev-,onlatest=true`,
`suffix=-alpine,onlatest=true`,
],
{
latest: "auto",
prefix: "dev-",
prefixLatest: true,
suffix: "-alpine",
suffixLatest: true,
} as Flavor, } as Flavor,
false false
], ],

View File

@ -1301,7 +1301,78 @@ describe('tag', () => {
"org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071",
"org.opencontainers.image.licenses=MIT" "org.opencontainers.image.licenses=MIT"
] ]
] ],
[
'tag21',
'event_tag_v1.1.1.env',
{
images: ['org/app', 'ghcr.io/user/app'],
tags: [
`type=semver,pattern={{version}}`,
`type=semver,pattern={{major}}.{{minor}}.{{patch}}`
],
flavor: [
`suffix=-dev,onlatest=true`
]
} as Inputs,
{
main: '1.1.1-dev',
partial: [],
latest: true
} as Version,
[
'org/app:1.1.1-dev',
'org/app:latest-dev',
'ghcr.io/user/app:1.1.1-dev',
'ghcr.io/user/app:latest-dev'
],
[
"org.opencontainers.image.title=Hello-World",
"org.opencontainers.image.description=This your first repo!",
"org.opencontainers.image.url=https://github.com/octocat/Hello-World",
"org.opencontainers.image.source=https://github.com/octocat/Hello-World",
"org.opencontainers.image.version=1.1.1-dev",
"org.opencontainers.image.created=2020-01-10T00:30:00.000Z",
"org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071",
"org.opencontainers.image.licenses=MIT"
]
],
[
'tag22',
'event_tag_v1.1.1.env',
{
images: ['org/app', 'ghcr.io/user/app'],
tags: [
`type=semver,pattern={{version}}`,
`type=semver,pattern={{major}}.{{minor}}.{{patch}}`
],
flavor: [
`prefix=foo-,onlatest=true`,
`suffix=-dev,onlatest=true`
]
} as Inputs,
{
main: 'foo-1.1.1-dev',
partial: [],
latest: true
} as Version,
[
'org/app:foo-1.1.1-dev',
'org/app:foo-latest-dev',
'ghcr.io/user/app:foo-1.1.1-dev',
'ghcr.io/user/app:foo-latest-dev'
],
[
"org.opencontainers.image.title=Hello-World",
"org.opencontainers.image.description=This your first repo!",
"org.opencontainers.image.url=https://github.com/octocat/Hello-World",
"org.opencontainers.image.source=https://github.com/octocat/Hello-World",
"org.opencontainers.image.version=foo-1.1.1-dev",
"org.opencontainers.image.created=2020-01-10T00:30:00.000Z",
"org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071",
"org.opencontainers.image.licenses=MIT"
]
],
])('given %p with %p event', tagsLabelsTest); ])('given %p with %p event', tagsLabelsTest);
}); });

82
dist/index.js generated vendored
View File

@ -129,45 +129,78 @@ var __importStar = (this && this.__importStar) || function (mod) {
__setModuleDefault(result, mod); __setModuleDefault(result, mod);
return result; return result;
}; };
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Transform = void 0; exports.Transform = void 0;
const core = __importStar(__webpack_require__(2186)); const core = __importStar(__webpack_require__(2186));
const sync_1 = __importDefault(__webpack_require__(8750));
function Transform(inputs) { function Transform(inputs) {
const flavor = { const flavor = {
latest: 'auto', latest: 'auto',
prefix: '', prefix: '',
suffix: '' prefixLatest: false,
suffix: '',
suffixLatest: false
}; };
for (const input of inputs) { for (const input of inputs) {
const parts = input.split('=', 2); const fields = sync_1.default(input, {
if (parts.length == 1) { relaxColumnCount: true,
throw new Error(`Invalid entry: ${input}`); skipLinesWithEmptyValues: true
} })[0];
switch (parts[0]) { let onlatestfor = '';
case 'latest': { for (const field of fields) {
flavor.latest = parts[1]; const parts = field.toString().split('=', 2);
if (!['auto', 'true', 'false'].includes(flavor.latest)) { if (parts.length == 1) {
throw new Error(`Invalid latest flavor entry: ${input}`); throw new Error(`Invalid flavor entry: ${input}`);
}
switch (parts[0]) {
case 'latest': {
flavor.latest = parts[1];
if (!['auto', 'true', 'false'].includes(flavor.latest)) {
throw new Error(`Invalid latest flavor entry: ${input}`);
}
break;
}
case 'prefix': {
flavor.prefix = parts[1];
onlatestfor = 'prefix';
break;
}
case 'suffix': {
flavor.suffix = parts[1];
onlatestfor = 'suffix';
break;
}
case 'onlatest': {
if (!['true', 'false'].includes(parts[1])) {
throw new Error(`Invalid value for onlatest attribute: ${parts[1]}`);
}
switch (onlatestfor) {
case 'prefix': {
flavor.prefixLatest = /true/i.test(parts[1]);
break;
}
case 'suffix': {
flavor.suffixLatest = /true/i.test(parts[1]);
break;
}
}
break;
}
default: {
throw new Error(`Unknown flavor entry: ${input}`);
} }
break;
}
case 'prefix': {
flavor.prefix = parts[1];
break;
}
case 'suffix': {
flavor.suffix = parts[1];
break;
}
default: {
throw new Error(`Unknown entry: ${input}`);
} }
} }
} }
core.startGroup(`Processing flavor input`); core.startGroup(`Processing flavor input`);
core.info(`latest=${flavor.latest}`); core.info(`latest=${flavor.latest}`);
core.info(`prefix=${flavor.prefix}`); core.info(`prefix=${flavor.prefix}`);
core.info(`prefixLatest=${flavor.prefixLatest}`);
core.info(`suffix=${flavor.suffix}`); core.info(`suffix=${flavor.suffix}`);
core.info(`suffixLatest=${flavor.suffixLatest}`);
core.endGroup(); core.endGroup();
return flavor; return flavor;
} }
@ -501,7 +534,6 @@ class Meta {
else { else {
vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-'); vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-');
} }
let latest = false;
let tmatch; let tmatch;
const isRegEx = tag.attrs['pattern'].match(/^\/(.+)\/(.*)$/); const isRegEx = tag.attrs['pattern'].match(/^\/(.+)\/(.*)$/);
if (isRegEx) { if (isRegEx) {
@ -633,7 +665,7 @@ class Meta {
tags.push(`${imageLc}:${partial}`); tags.push(`${imageLc}:${partial}`);
} }
if (this.version.latest) { if (this.version.latest) {
tags.push(`${imageLc}:latest`); tags.push(`${imageLc}:${this.flavor.prefixLatest ? this.flavor.prefix : ''}latest${this.flavor.suffixLatest ? this.flavor.suffix : ''}`);
} }
} }
return tags; return tags;
@ -817,7 +849,7 @@ function Parse(s) {
switch (key) { switch (key) {
case 'type': { case 'type': {
if (!Object.values(Type).includes(value)) { if (!Object.values(Type).includes(value)) {
throw new Error(`Unknown type attribute: ${value}`); throw new Error(`Unknown tag type attribute: ${value}`);
} }
tag.type = value; tag.type = value;
break; break;

View File

@ -1,41 +1,71 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import csvparse from 'csv-parse/lib/sync';
export interface Flavor { export interface Flavor {
latest: string; latest: string;
prefix: string; prefix: string;
prefixLatest: boolean;
suffix: string; suffix: string;
suffixLatest: boolean;
} }
export function Transform(inputs: string[]): Flavor { export function Transform(inputs: string[]): Flavor {
const flavor: Flavor = { const flavor: Flavor = {
latest: 'auto', latest: 'auto',
prefix: '', prefix: '',
suffix: '' prefixLatest: false,
suffix: '',
suffixLatest: false
}; };
for (const input of inputs) { for (const input of inputs) {
const parts = input.split('=', 2); const fields = csvparse(input, {
if (parts.length == 1) { relaxColumnCount: true,
throw new Error(`Invalid entry: ${input}`); skipLinesWithEmptyValues: true
} })[0];
switch (parts[0]) { let onlatestfor = '';
case 'latest': { for (const field of fields) {
flavor.latest = parts[1]; const parts = field.toString().split('=', 2);
if (!['auto', 'true', 'false'].includes(flavor.latest)) { if (parts.length == 1) {
throw new Error(`Invalid latest flavor entry: ${input}`); throw new Error(`Invalid flavor entry: ${input}`);
}
switch (parts[0]) {
case 'latest': {
flavor.latest = parts[1];
if (!['auto', 'true', 'false'].includes(flavor.latest)) {
throw new Error(`Invalid latest flavor entry: ${input}`);
}
break;
}
case 'prefix': {
flavor.prefix = parts[1];
onlatestfor = 'prefix';
break;
}
case 'suffix': {
flavor.suffix = parts[1];
onlatestfor = 'suffix';
break;
}
case 'onlatest': {
if (!['true', 'false'].includes(parts[1])) {
throw new Error(`Invalid value for onlatest attribute: ${parts[1]}`);
}
switch (onlatestfor) {
case 'prefix': {
flavor.prefixLatest = /true/i.test(parts[1]);
break;
}
case 'suffix': {
flavor.suffixLatest = /true/i.test(parts[1]);
break;
}
}
break;
}
default: {
throw new Error(`Unknown flavor entry: ${input}`);
} }
break;
}
case 'prefix': {
flavor.prefix = parts[1];
break;
}
case 'suffix': {
flavor.suffix = parts[1];
break;
}
default: {
throw new Error(`Unknown entry: ${input}`);
} }
} }
} }
@ -43,7 +73,9 @@ export function Transform(inputs: string[]): Flavor {
core.startGroup(`Processing flavor input`); core.startGroup(`Processing flavor input`);
core.info(`latest=${flavor.latest}`); core.info(`latest=${flavor.latest}`);
core.info(`prefix=${flavor.prefix}`); core.info(`prefix=${flavor.prefix}`);
core.info(`prefixLatest=${flavor.prefixLatest}`);
core.info(`suffix=${flavor.suffix}`); core.info(`suffix=${flavor.suffix}`);
core.info(`suffixLatest=${flavor.suffixLatest}`);
core.endGroup(); core.endGroup();
return flavor; return flavor;

View File

@ -159,7 +159,6 @@ export class Meta {
vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-'); vraw = this.context.ref.replace(/^refs\/tags\//g, '').replace(/\//g, '-');
} }
let latest: boolean = false;
let tmatch; let tmatch;
const isRegEx = tag.attrs['pattern'].match(/^\/(.+)\/(.*)$/); const isRegEx = tag.attrs['pattern'].match(/^\/(.+)\/(.*)$/);
if (isRegEx) { if (isRegEx) {
@ -304,7 +303,7 @@ export class Meta {
tags.push(`${imageLc}:${partial}`); tags.push(`${imageLc}:${partial}`);
} }
if (this.version.latest) { if (this.version.latest) {
tags.push(`${imageLc}:latest`); tags.push(`${imageLc}:${this.flavor.prefixLatest ? this.flavor.prefix : ''}latest${this.flavor.suffixLatest ? this.flavor.suffix : ''}`);
} }
} }
return tags; return tags;

View File

@ -100,7 +100,7 @@ export function Parse(s: string): Tag {
switch (key) { switch (key) {
case 'type': { case 'type': {
if (!Object.values(Type).includes(value)) { if (!Object.values(Type).includes(value)) {
throw new Error(`Unknown type attribute: ${value}`); throw new Error(`Unknown tag type attribute: ${value}`);
} }
tag.type = value; tag.type = value;
break; break;