mirror of
https://github.com/docker/metadata-action.git
synced 2026-04-07 02:26:53 +00:00
feat: enable customization of annotations+labels
Signed-off-by: Brendon Smith <bws@bws.bio>
This commit is contained in:
parent
b13d25e5fc
commit
de96cf9194
4 changed files with 320 additions and 100 deletions
97
src/annotation.ts
Normal file
97
src/annotation.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import {parse} from 'csv-parse/sync';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
export interface Annotation {
|
||||
name: string;
|
||||
value: string | null;
|
||||
enable: boolean;
|
||||
}
|
||||
|
||||
export function Transform(inputs: string[]): Annotation[] {
|
||||
let annotations: Annotation[] = [];
|
||||
|
||||
for (const input of inputs) {
|
||||
const annotation: Annotation = {name: '', value: null, enable: true};
|
||||
const fields = parse(input, {
|
||||
relaxColumnCount: true,
|
||||
relaxQuotes: true,
|
||||
skipEmptyLines: true
|
||||
})[0];
|
||||
let usesAttributes = false;
|
||||
|
||||
for (const field of fields) {
|
||||
const parts = field
|
||||
.toString()
|
||||
.split('=')
|
||||
.map(item => item.trim());
|
||||
if (parts.length > 0) {
|
||||
const key = parts[0].toLowerCase();
|
||||
if (['name', 'value', 'enable'].includes(key)) {
|
||||
usesAttributes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usesAttributes) {
|
||||
for (const field of fields) {
|
||||
const parts = field
|
||||
.toString()
|
||||
.split('=')
|
||||
.map(item => item.trim());
|
||||
if (parts.length === 1) {
|
||||
annotation.name = parts[0];
|
||||
} else {
|
||||
const key = parts[0].toLowerCase();
|
||||
const value = parts.slice(1).join('='); // preserve '=' in values if any
|
||||
switch (key) {
|
||||
case 'name': {
|
||||
annotation.name = value;
|
||||
break;
|
||||
}
|
||||
case 'value': {
|
||||
annotation.value = value;
|
||||
break;
|
||||
}
|
||||
case 'enable': {
|
||||
if (!['true', 'false'].includes(value.toLowerCase())) {
|
||||
throw new Error(`Invalid enable attribute value: ${input}`);
|
||||
}
|
||||
annotation.enable = /true/i.test(value);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error(`Unknown annotation attribute: ${input}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const idx = input.indexOf('=');
|
||||
if (idx === -1) {
|
||||
annotation.name = input.trim();
|
||||
} else {
|
||||
annotation.name = input.substring(0, idx).trim();
|
||||
annotation.value = input.substring(idx + 1).trim();
|
||||
}
|
||||
annotation.enable = true;
|
||||
}
|
||||
|
||||
if (annotation.name.length === 0) {
|
||||
throw new Error(`Annotation name attribute empty: ${input}`);
|
||||
}
|
||||
|
||||
annotations.push(annotation);
|
||||
}
|
||||
|
||||
return output(annotations);
|
||||
}
|
||||
|
||||
function output(annotations: Annotation[]): Annotation[] {
|
||||
core.startGroup(`Processing annotations input`);
|
||||
for (const annotation of annotations) {
|
||||
core.info(`name=${annotation.name},value=${annotation.value},enable=${annotation.enable}`);
|
||||
}
|
||||
core.endGroup();
|
||||
return annotations;
|
||||
}
|
||||
19
src/meta.ts
19
src/meta.ts
|
|
@ -12,6 +12,7 @@ import {Inputs, Context} from './context.js';
|
|||
import * as icl from './image.js';
|
||||
import * as tcl from './tag.js';
|
||||
import * as fcl from './flavor.js';
|
||||
import * as acl from './annotation.js';
|
||||
|
||||
const defaultShortShaLength = 7;
|
||||
|
||||
|
|
@ -30,6 +31,8 @@ export class Meta {
|
|||
private readonly images: icl.Image[];
|
||||
private readonly tags: tcl.Tag[];
|
||||
private readonly flavor: fcl.Flavor;
|
||||
private readonly annotations: acl.Annotation[];
|
||||
private readonly labels: acl.Annotation[];
|
||||
private readonly date: Date;
|
||||
|
||||
constructor(inputs: Inputs, context: Context, repo: GitHubRepo) {
|
||||
|
|
@ -39,6 +42,8 @@ export class Meta {
|
|||
this.images = icl.Transform(inputs.images);
|
||||
this.tags = tcl.Transform(inputs.tags);
|
||||
this.flavor = fcl.Transform(inputs.flavor);
|
||||
this.annotations = acl.Transform(inputs.annotations);
|
||||
this.labels = acl.Transform(inputs.labels);
|
||||
this.date = new Date();
|
||||
this.version = this.getVersion();
|
||||
}
|
||||
|
|
@ -530,14 +535,14 @@ export class Meta {
|
|||
}
|
||||
|
||||
public getLabels(): Array<string> {
|
||||
return this.getOCIAnnotationsWithCustoms(this.inputs.labels);
|
||||
return this.getOCIAnnotationsWithCustoms(this.labels);
|
||||
}
|
||||
|
||||
public getAnnotations(): Array<string> {
|
||||
return this.getOCIAnnotationsWithCustoms(this.inputs.annotations);
|
||||
return this.getOCIAnnotationsWithCustoms(this.annotations);
|
||||
}
|
||||
|
||||
private getOCIAnnotationsWithCustoms(extra: string[]): Array<string> {
|
||||
private getOCIAnnotationsWithCustoms(annotations: acl.Annotation[]): Array<string> {
|
||||
const res: Array<string> = [
|
||||
`org.opencontainers.image.title=${this.repo.name || ''}`,
|
||||
`org.opencontainers.image.description=${this.repo.description || ''}`,
|
||||
|
|
@ -548,10 +553,12 @@ export class Meta {
|
|||
`org.opencontainers.image.revision=${this.context.sha || ''}`,
|
||||
`org.opencontainers.image.licenses=${this.repo.license?.spdx_id || ''}`
|
||||
];
|
||||
extra.forEach(label => {
|
||||
res.push(this.setGlobalExp(label));
|
||||
annotations.forEach(annotation => {
|
||||
if (annotation.enable && annotation.value != null) {
|
||||
const expandedValue = this.setGlobalExp(annotation.value);
|
||||
res.push(`${annotation.name}=${expandedValue}`);
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(
|
||||
new Map<string, string>(
|
||||
res
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue