diff --git a/README.md b/README.md index 623df688..f99781aa 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,8 @@ Following inputs can be used as `step.with` keys | `tag-schedule` | String | [Template](#schedule-tag) to apply to schedule tag (default `nightly`) | | `sep-tags` | String | Separator to use for tags output (default `\n`) | | `sep-labels` | String | Separator to use for labels output (default `\n`) | +| `flavor` | String | Tag suffix to be appended, specifying the image flavor (default ``) | +| `main-flavor` | String | Enable tags without flavor suffix (default `true`) | > List/CSV type can be a newline or comma delimited string @@ -306,6 +308,18 @@ If Git tag is a valid [semver](https://semver.org/) you can handle it to output | `release1` | `\d{1,3}.\d{1,3}` | `0` | :x: | `release1` | `release1` | | `20200110-RC2` | `\d+` | `0` | :white_check_mark: | `20200110`, `latest` | `20200110` | +### `flavor` examples + +| Git tag | `flavor` | `main-flavor` | `tag-latest` | Output tags | +|-------------------------|----------|---------------|--------------|---------------------------------------------| +| `v1.2.3` | `debian` | `true` | `true` | `1.2.3-debian`, `1.2.3`, `debian`, `latest` | +| `v1.2.3` | `debian` | `true` | `false` | `1.2.3-debian`, `1.2.3` | +| `v1.2.3` | `alpine` | `false` | `true` | `1.2.3-alpine`, `alpine` | +| `v1.2.3` | `alpine` | `false` | `false` | `1.2.3-alpine` | +| `v1.2.3` | `` | `` | `true` | `1.2.3`, `latest` | +| `v1.2.3` | `` | `` | `false` | `1.2.3` | + + ### Schedule tag `tag-schedule` is specially crafted input to support [Handlebars template](https://handlebarsjs.com/guide/) with diff --git a/__tests__/meta.test.ts b/__tests__/meta.test.ts index ad63e7fd..a3c88bd6 100644 --- a/__tests__/meta.test.ts +++ b/__tests__/meta.test.ts @@ -1229,3 +1229,206 @@ describe('release', () => { ], ])('given %p event ', tagsLabelsTest); }); + +describe('flavor', () => { + // prettier-ignore + test.each([ + [ + 'event_release.env', + { + images: ['user/app'], + flavor: 'debian', + mainFlavor: true, + } as Inputs, + { + main: 'v1.1.1', + partial: [], + latest: true + } as Version, + [ + 'user/app:v1.1.1', + 'user/app:v1.1.1-debian', + 'user/app:latest', + 'user/app:debian', + ], + [ + "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=v1.1.1", + "org.opencontainers.image.created=2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", + "org.opencontainers.image.licenses=MIT" + ] + ], + [ + 'event_release.env', + { + images: ['user/app'], + flavor: 'debian', + mainFlavor: true, + tagLatest: false, + } as Inputs, + { + main: 'v1.1.1', + partial: [], + latest: false, + } as Version, + [ + 'user/app:v1.1.1', + 'user/app:v1.1.1-debian', + ], + [ + "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=v1.1.1", + "org.opencontainers.image.created=2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", + "org.opencontainers.image.licenses=MIT" + ] + ], + [ + 'event_release.env', + { + images: ['user/app'], + flavor: 'alpine', + mainFlavor: false, + } as Inputs, + { + main: 'v1.1.1', + partial: [], + latest: true + } as Version, + [ + 'user/app:v1.1.1-alpine', + 'user/app:alpine', + ], + [ + "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=v1.1.1", + "org.opencontainers.image.created=2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", + "org.opencontainers.image.licenses=MIT" + ] + ], + [ + 'event_release.env', + { + images: ['user/app'], + flavor: 'alpine', + mainFlavor: false, + tagLatest: false, + } as Inputs, + { + main: 'v1.1.1', + partial: [], + latest: false + } as Version, + [ + 'user/app:v1.1.1-alpine', + ], + [ + "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=v1.1.1", + "org.opencontainers.image.created=2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", + "org.opencontainers.image.licenses=MIT" + ] + ], + [ + 'event_release.env', + { + images: ['user/app'], + flavor: '', + mainFlavor: true, + tagLatest: false, + } as Inputs, + { + main: 'v1.1.1', + partial: [], + latest: false + } as Version, + [ + 'user/app:v1.1.1', + ], + [ + "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=v1.1.1", + "org.opencontainers.image.created=2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", + "org.opencontainers.image.licenses=MIT" + ] + ], + [ + 'event_release.env', + { + images: ['user/app'], + flavor: '', + mainFlavor: false, + tagLatest: false, + } as Inputs, + { + main: 'v1.1.1', + partial: [], + latest: false + } as Version, + [ + 'user/app:v1.1.1', + ], + [ + "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=v1.1.1", + "org.opencontainers.image.created=2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", + "org.opencontainers.image.licenses=MIT" + ] + ], + [ + 'event_release.env', + { + images: ['user/app'], + tagSemver: ['{{version}}', '{{major}}.{{minor}}', '{{major}}'], + tagSha: true, + flavor: 'alpine', + mainFlavor: false, + } as Inputs, + { + main: '1.1.1', + partial: ['1.1', '1'], + latest: true + } as Version, + [ + 'user/app:1.1.1-alpine', + 'user/app:1.1-alpine', + 'user/app:1-alpine', + 'user/app:alpine', + 'user/app:sha-90dd603-alpine', + ], + [ + "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", + "org.opencontainers.image.created=2020-01-10T00:30:00.000Z", + "org.opencontainers.image.revision=90dd6032fac8bda1b6c4436a2e65de27961ed071", + "org.opencontainers.image.licenses=MIT" + ] + ], + ])('given %p event ', tagsLabelsTest); +}); diff --git a/action.yml b/action.yml index 8eadd195..f2e7060f 100644 --- a/action.yml +++ b/action.yml @@ -54,6 +54,13 @@ inputs: description: 'GitHub Token as provided by secrets' default: ${{ github.token }} required: true + flavor: + description: 'Container flavor, with no leading dash, like "alpine" or "debian"' + required: false + main-flavor: + description: 'Create tags without flavor as well' + default: 'true' + required: false outputs: version: diff --git a/dist/index.js b/dist/index.js index 72fb6437..edab5a1f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -32,7 +32,9 @@ function getInputs() { tagSchedule: core.getInput('tag-schedule') || 'nightly', sepTags: core.getInput('sep-tags') || `\n`, sepLabels: core.getInput('sep-labels') || `\n`, - githubToken: core.getInput('github-token') + githubToken: core.getInput('github-token'), + flavor: core.getInput('flavor'), + mainFlavor: /true/i.test(core.getInput('main-flavor') || 'true') }; } exports.getInputs = getInputs; @@ -255,18 +257,40 @@ class Meta { if (!this.version.main) { return []; } + let flavor = this.inputs.flavor; + let main = !flavor || this.inputs.mainFlavor; let tags = []; for (const image of this.inputs.images) { const imageLc = image.toLowerCase(); - tags.push(`${imageLc}:${this.version.main}`); + if (main) { + tags.push(`${imageLc}:${this.version.main}`); + } + if (flavor) { + tags.push(`${imageLc}:${this.version.main}-${flavor}`); + } for (const partial of this.version.partial) { - tags.push(`${imageLc}:${partial}`); + if (main) { + tags.push(`${imageLc}:${partial}`); + } + if (flavor) { + tags.push(`${imageLc}:${partial}-${flavor}`); + } } if (this.version.latest) { - tags.push(`${imageLc}:latest`); + if (main) { + tags.push(`${imageLc}:latest`); + } + if (flavor) { + tags.push(`${imageLc}:${flavor}`); + } } if (this.context.sha && this.inputs.tagSha) { - tags.push(`${imageLc}:sha-${this.context.sha.substr(0, 7)}`); + if (main) { + tags.push(`${imageLc}:sha-${this.context.sha.substr(0, 7)}`); + } + if (flavor) { + tags.push(`${imageLc}:sha-${this.context.sha.substr(0, 7)}-${flavor}`); + } } } return tags; diff --git a/src/context.ts b/src/context.ts index e50221da..69517db5 100644 --- a/src/context.ts +++ b/src/context.ts @@ -13,6 +13,8 @@ export interface Inputs { sepTags: string; sepLabels: string; githubToken: string; + flavor: string; + mainFlavor: boolean; } export function getInputs(): Inputs { @@ -28,7 +30,9 @@ export function getInputs(): Inputs { tagSchedule: core.getInput('tag-schedule') || 'nightly', sepTags: core.getInput('sep-tags') || `\n`, sepLabels: core.getInput('sep-labels') || `\n`, - githubToken: core.getInput('github-token') + githubToken: core.getInput('github-token'), + flavor: core.getInput('flavor'), + mainFlavor: /true/i.test(core.getInput('main-flavor') || 'true') }; } diff --git a/src/meta.ts b/src/meta.ts index 8fae9b94..aff74fb8 100644 --- a/src/meta.ts +++ b/src/meta.ts @@ -100,18 +100,41 @@ export class Meta { return []; } + let flavor = this.inputs.flavor; + let main = !flavor || this.inputs.mainFlavor; + let tags: Array = []; for (const image of this.inputs.images) { const imageLc = image.toLowerCase(); - tags.push(`${imageLc}:${this.version.main}`); + if (main) { + tags.push(`${imageLc}:${this.version.main}`); + } + if (flavor) { + tags.push(`${imageLc}:${this.version.main}-${flavor}`); + } for (const partial of this.version.partial) { - tags.push(`${imageLc}:${partial}`); + if (main) { + tags.push(`${imageLc}:${partial}`); + } + if (flavor) { + tags.push(`${imageLc}:${partial}-${flavor}`); + } } if (this.version.latest) { - tags.push(`${imageLc}:latest`); + if (main) { + tags.push(`${imageLc}:latest`); + } + if (flavor) { + tags.push(`${imageLc}:${flavor}`); + } } if (this.context.sha && this.inputs.tagSha) { - tags.push(`${imageLc}:sha-${this.context.sha.substr(0, 7)}`); + if (main) { + tags.push(`${imageLc}:sha-${this.context.sha.substr(0, 7)}`); + } + if (flavor) { + tags.push(`${imageLc}:sha-${this.context.sha.substr(0, 7)}-${flavor}`); + } } } return tags;