Add label-custom input (#35)
Co-authored-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									c48ac80f46
								
							
						
					
					
						commit
						3479bd5aaa
					
				
							
								
								
									
										18
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							| @ -2,7 +2,8 @@ | ||||
| 
 | ||||
| Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. | ||||
| 
 | ||||
| Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE). | ||||
| Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) | ||||
| to the public under the [project's open source license](LICENSE). | ||||
| 
 | ||||
| ## Submitting a pull request | ||||
| 
 | ||||
| @ -16,21 +17,6 @@ Contributions to this project are [released](https://help.github.com/articles/gi | ||||
| 8. Push to your fork and [submit a pull request](https://github.com/crazy-max/ghaction-docker-meta/compare) | ||||
| 9. Pat your self on the back and wait for your pull request to be reviewed and merged. | ||||
| 
 | ||||
| ## Container based developer flow | ||||
| 
 | ||||
| If you don't want to maintain a Node developer environment that fits this project you can use containerized commands instead of invoking yarn directly. | ||||
| 
 | ||||
| ``` | ||||
| # format code and build javascript artifacts | ||||
| docker buildx bake pre-checkin | ||||
| 
 | ||||
| # validate all code has correctly formatted and built | ||||
| docker buildx bake validate | ||||
| 
 | ||||
| # run tests | ||||
| docker buildx bake test | ||||
| ``` | ||||
| 
 | ||||
| Here are a few things you can do that will increase the likelihood of your pull request being accepted: | ||||
| 
 | ||||
| - Write tests. | ||||
|  | ||||
							
								
								
									
										19
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @ -105,6 +105,25 @@ jobs: | ||||
|             {{major}}.{{minor}}.{{patch}} | ||||
|           tag-latest: ${{ matrix.tag-latest }} | ||||
| 
 | ||||
|   label-custom: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Docker meta | ||||
|         uses: ./ | ||||
|         with: | ||||
|           images: | | ||||
|             ${{ env.DOCKER_IMAGE }} | ||||
|             ghcr.io/name/app | ||||
|           label-custom: | | ||||
|             maintainer=CrazyMax | ||||
|             org.opencontainers.image.title=MyCustomTitle | ||||
|             org.opencontainers.image.description=Another description | ||||
|             org.opencontainers.image.vendor=MyCompany | ||||
| 
 | ||||
|   docker-push: | ||||
|     runs-on: ubuntu-latest | ||||
|     services: | ||||
|  | ||||
							
								
								
									
										45
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								README.md
									
									
									
									
									
								
							| @ -31,7 +31,7 @@ ___ | ||||
|   * [Schedule tag](#schedule-tag) | ||||
|   * [Overwrite labels](#overwrite-labels) | ||||
| * [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot) | ||||
| * [How can I help?](#how-can-i-help) | ||||
| * [Contributing](#contributing) | ||||
| * [License](#license) | ||||
| 
 | ||||
| ## Features | ||||
| @ -235,6 +235,19 @@ jobs: | ||||
| 
 | ||||
| Following inputs can be used as `step.with` keys | ||||
| 
 | ||||
| > `List` type is a newline-delimited string | ||||
| > ```yaml | ||||
| > label-custom: | | ||||
| >   org.opencontainers.image.title=MyCustomTitle | ||||
| >   org.opencontainers.image.description=Another description | ||||
| >   org.opencontainers.image.vendor=MyCompany | ||||
| > ``` | ||||
| 
 | ||||
| > `CSV` type is a comma-delimited string | ||||
| > ```yaml | ||||
| > images: name/app,ghcr.io/name/app | ||||
| > ``` | ||||
| 
 | ||||
| | Name                | Type     | Description                        | | ||||
| |---------------------|----------|------------------------------------| | ||||
| | `images`            | List/CSV | List of Docker images to use as base name for tags | | ||||
| @ -248,11 +261,10 @@ Following inputs can be used as `step.with` keys | ||||
| | `tag-schedule`      | String   | [Template](#schedule-tag) to apply to schedule tag (default `nightly`) | | ||||
| | `tag-custom`        | List/CSV | List of custom tags | | ||||
| | `tag-custom-only`   | Bool     | Only use `tag-custom` as Docker tags | | ||||
| | `label-custom`      | List     | List of custom labels | | ||||
| | `sep-tags`          | String   | Separator to use for tags output (default `\n`) | | ||||
| | `sep-labels`        | String   | Separator to use for labels output (default `\n`) | | ||||
| 
 | ||||
| > List/CSV type can be a newline or comma delimited string | ||||
| 
 | ||||
| > `tag-semver` and `tag-match` are mutually exclusive | ||||
| 
 | ||||
| ### outputs | ||||
| @ -326,16 +338,13 @@ labels generated are not suitable, you can overwrite them like this: | ||||
| 
 | ||||
| ```yaml | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         name: Docker meta | ||||
|         id: docker_meta | ||||
|         uses: crazy-max/ghaction-docker-meta@v1 | ||||
|         with: | ||||
|           context: . | ||||
|           file: ./Dockerfile | ||||
|           platforms: linux/amd64,linux/arm64,linux/386 | ||||
|           push: ${{ github.event_name != 'pull_request' }} | ||||
|           tags: ${{ steps.docker_meta.outputs.tags }} | ||||
|           labels: | | ||||
|             ${{ steps.docker_meta.outputs.labels }} | ||||
|           images: name/app | ||||
|           label-custom: | | ||||
|             maintainer=CrazyMax | ||||
|             org.opencontainers.image.title=MyCustomTitle | ||||
|             org.opencontainers.image.description=Another description | ||||
|             org.opencontainers.image.vendor=MyCompany | ||||
| @ -357,12 +366,14 @@ updates: | ||||
|       interval: "daily" | ||||
| ``` | ||||
| 
 | ||||
| ## How can I help? | ||||
| # Contributing | ||||
| 
 | ||||
| All kinds of contributions are welcome :raised_hands:! The most basic way to show your support is to star :star2: | ||||
| the project, or to raise issues :speech_balloon: You can also support this project by | ||||
| [**becoming a sponsor on GitHub**](https://github.com/sponsors/crazy-max) :clap: or by making a | ||||
| [Paypal donation](https://www.paypal.me/crazyws) to ensure this journey continues indefinitely! :rocket: | ||||
| Want to contribute? Awesome! The most basic way to show your support is to star :star2: the project, | ||||
| or to raise issues :speech_balloon:. If you want to open a pull request, please read the | ||||
| [contributing guidelines](.github/CONTRIBUTING.md). | ||||
| 
 | ||||
| You can also support this project by [**becoming a sponsor on GitHub**](https://github.com/sponsors/crazy-max) or by | ||||
| making a [Paypal donation](https://www.paypal.me/crazyws) to ensure this journey continues indefinitely! | ||||
| 
 | ||||
| Thanks again for your support, it is much appreciated! :pray: | ||||
| 
 | ||||
|  | ||||
| @ -1,54 +1,150 @@ | ||||
| import * as context from '../src/context'; | ||||
| 
 | ||||
| describe('getInputList', () => { | ||||
|   it('handles single line correctly', async () => { | ||||
|   it('single line correctly', async () => { | ||||
|     await setInput('foo', 'bar'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar']); | ||||
|   }); | ||||
| 
 | ||||
|   it('handles multiple lines correctly', async () => { | ||||
|   it('multiline correctly', async () => { | ||||
|     setInput('foo', 'bar\nbaz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
| 
 | ||||
|   it('remove empty lines correctly', async () => { | ||||
|   it('empty lines correctly', async () => { | ||||
|     setInput('foo', 'bar\n\nbaz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
| 
 | ||||
|   it('handles comma correctly', async () => { | ||||
|   it('comma correctly', async () => { | ||||
|     setInput('foo', 'bar,baz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
| 
 | ||||
|   it('remove empty result correctly', async () => { | ||||
|   it('empty result correctly', async () => { | ||||
|     setInput('foo', 'bar,baz,'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
| 
 | ||||
|   it('handles different new lines correctly', async () => { | ||||
|   it('different new lines correctly', async () => { | ||||
|     setInput('foo', 'bar\r\nbaz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
| 
 | ||||
|   it('handles different new lines and comma correctly', async () => { | ||||
|   it('different new lines and comma correctly', async () => { | ||||
|     setInput('foo', 'bar\r\nbaz,bat'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz', 'bat']); | ||||
|   }); | ||||
| 
 | ||||
|   it('multiline and ignoring comma correctly', async () => { | ||||
|     setInput('cache-from', 'user/app:cache\ntype=local,src=path/to/dir'); | ||||
|     const res = await context.getInputList('cache-from', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']); | ||||
|   }); | ||||
| 
 | ||||
|   it('different new lines and ignoring comma correctly', async () => { | ||||
|     setInput('cache-from', 'user/app:cache\r\ntype=local,src=path/to/dir'); | ||||
|     const res = await context.getInputList('cache-from', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']); | ||||
|   }); | ||||
| 
 | ||||
|   it('multiline values', async () => { | ||||
|     setInput( | ||||
|       'secrets', | ||||
|       `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
 | ||||
| "MYSECRET=aaaaaaaa | ||||
| bbbbbbb | ||||
| ccccccccc" | ||||
| FOO=bar` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([ | ||||
|       'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', | ||||
|       `MYSECRET=aaaaaaaa
 | ||||
| bbbbbbb | ||||
| ccccccccc`,
 | ||||
|       'FOO=bar' | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('multiline values with empty lines', async () => { | ||||
|     setInput( | ||||
|       'secrets', | ||||
|       `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
 | ||||
| "MYSECRET=aaaaaaaa | ||||
| bbbbbbb | ||||
| ccccccccc" | ||||
| FOO=bar | ||||
| "EMPTYLINE=aaaa | ||||
| 
 | ||||
| bbbb | ||||
| ccc"` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([ | ||||
|       'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', | ||||
|       `MYSECRET=aaaaaaaa
 | ||||
| bbbbbbb | ||||
| ccccccccc`,
 | ||||
|       'FOO=bar', | ||||
|       `EMPTYLINE=aaaa
 | ||||
| 
 | ||||
| bbbb | ||||
| ccc` | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('multiline values without quotes', async () => { | ||||
|     setInput( | ||||
|       'secrets', | ||||
|       `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
 | ||||
| MYSECRET=aaaaaaaa | ||||
| bbbbbbb | ||||
| ccccccccc | ||||
| FOO=bar` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', 'MYSECRET=aaaaaaaa', 'bbbbbbb', 'ccccccccc', 'FOO=bar']); | ||||
|   }); | ||||
| 
 | ||||
|   it('multiline values escape quotes', async () => { | ||||
|     setInput( | ||||
|       'secrets', | ||||
|       `GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
 | ||||
| "MYSECRET=aaaaaaaa | ||||
| bbbb""bbb | ||||
| ccccccccc" | ||||
| FOO=bar` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([ | ||||
|       'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', | ||||
|       `MYSECRET=aaaaaaaa
 | ||||
| bbbb\"bbb | ||||
| ccccccccc`,
 | ||||
|       'FOO=bar' | ||||
|     ]); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| describe('asyncForEach', () => { | ||||
|  | ||||
| @ -1009,6 +1009,42 @@ describe('latest', () => { | ||||
|         "org.opencontainers.image.licenses=MIT" | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       'event_tag_v1.1.1.env', | ||||
|       { | ||||
|         images: ['org/app', 'ghcr.io/MyUSER/MyApp'], | ||||
|         tagLatest: false, | ||||
|         labelCustom: [ | ||||
|           "maintainer=CrazyMax", | ||||
|           "org.opencontainers.image.title=MyCustomTitle", | ||||
|           "org.opencontainers.image.description=Another description", | ||||
|           "org.opencontainers.image.vendor=MyCompany", | ||||
|         ], | ||||
|       } as Inputs, | ||||
|       { | ||||
|         main: 'v1.1.1', | ||||
|         partial: [], | ||||
|         latest: false | ||||
|       } as Version, | ||||
|       [ | ||||
|         'org/app:v1.1.1', | ||||
|         'ghcr.io/myuser/myapp: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", | ||||
|         "maintainer=CrazyMax", | ||||
|         "org.opencontainers.image.title=MyCustomTitle", | ||||
|         "org.opencontainers.image.description=Another description", | ||||
|         "org.opencontainers.image.vendor=MyCompany" | ||||
|       ] | ||||
|     ], | ||||
|   ])('given %p event ', tagsLabelsTest); | ||||
| }); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										1461
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1461
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -25,6 +25,7 @@ | ||||
|   "dependencies": { | ||||
|     "@actions/core": "^1.2.6", | ||||
|     "@actions/github": "^4.0.0", | ||||
|     "csv-parse": "^4.14.2", | ||||
|     "handlebars": "^4.7.6", | ||||
|     "moment": "^2.29.1", | ||||
|     "semver": "^7.3.4" | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| import csvparse from 'csv-parse/lib/sync'; | ||||
| import * as core from '@actions/core'; | ||||
| 
 | ||||
| export interface Inputs { | ||||
| @ -12,6 +13,7 @@ export interface Inputs { | ||||
|   tagSchedule: string; | ||||
|   tagCustom: string[]; | ||||
|   tagCustomOnly: boolean; | ||||
|   labelCustom: string[]; | ||||
|   sepTags: string; | ||||
|   sepLabels: string; | ||||
|   githubToken: string; | ||||
| @ -30,21 +32,37 @@ export function getInputs(): Inputs { | ||||
|     tagSchedule: core.getInput('tag-schedule') || 'nightly', | ||||
|     tagCustom: getInputList('tag-custom'), | ||||
|     tagCustomOnly: /true/i.test(core.getInput('tag-custom-only') || 'false'), | ||||
|     labelCustom: getInputList('label-custom'), | ||||
|     sepTags: core.getInput('sep-tags') || `\n`, | ||||
|     sepLabels: core.getInput('sep-labels') || `\n`, | ||||
|     githubToken: core.getInput('github-token') | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| export function getInputList(name: string): string[] { | ||||
| export function getInputList(name: string, ignoreComma?: boolean): string[] { | ||||
|   let res: Array<string> = []; | ||||
| 
 | ||||
|   const items = core.getInput(name); | ||||
|   if (items == '') { | ||||
|     return []; | ||||
|     return res; | ||||
|   } | ||||
|   return items | ||||
|     .split(/\r?\n/) | ||||
|     .filter(x => x) | ||||
|     .reduce<string[]>((acc, line) => acc.concat(line.split(',').filter(x => x)).map(pat => pat.trim()), []); | ||||
| 
 | ||||
|   for (let output of csvparse(items, { | ||||
|     columns: false, | ||||
|     relaxColumnCount: true, | ||||
|     skipLinesWithEmptyValues: true | ||||
|   }) as Array<string[]>) { | ||||
|     if (output.length == 1) { | ||||
|       res.push(output[0]); | ||||
|       continue; | ||||
|     } else if (!ignoreComma) { | ||||
|       res.push(...output); | ||||
|       continue; | ||||
|     } | ||||
|     res.push(output.join(',')); | ||||
|   } | ||||
| 
 | ||||
|   return res.filter(item => item).map(pat => pat.trim()); | ||||
| } | ||||
| 
 | ||||
| export const asyncForEach = async (array, callback) => { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import * as handlebars from 'handlebars'; | ||||
| import * as moment from 'moment'; | ||||
| import moment from 'moment'; | ||||
| import * as semver from 'semver'; | ||||
| import {Inputs} from './context'; | ||||
| import * as core from '@actions/core'; | ||||
| @ -130,7 +130,7 @@ export class Meta { | ||||
|   } | ||||
| 
 | ||||
|   public labels(): Array<string> { | ||||
|     return [ | ||||
|     let labels: Array<string> = [ | ||||
|       `org.opencontainers.image.title=${this.repo.name || ''}`, | ||||
|       `org.opencontainers.image.description=${this.repo.description || ''}`, | ||||
|       `org.opencontainers.image.url=${this.repo.html_url || ''}`, | ||||
| @ -140,5 +140,7 @@ export class Meta { | ||||
|       `org.opencontainers.image.revision=${this.context.sha || ''}`, | ||||
|       `org.opencontainers.image.licenses=${this.repo.license?.spdx_id || ''}` | ||||
|     ]; | ||||
|     labels.push(...this.inputs.labelCustom); | ||||
|     return labels; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -11,9 +11,11 @@ | ||||
|     "rootDir": "./src", | ||||
|     "strict": true, | ||||
|     "noImplicitAny": false, | ||||
|     "esModuleInterop": false, | ||||
|     "resolveJsonModule": true, | ||||
|     "esModuleInterop": true, | ||||
|     "sourceMap": true | ||||
|   }, | ||||
|   "exclude": ["node_modules", "**/*.test.ts"] | ||||
|   "exclude": [ | ||||
|     "node_modules", | ||||
|     "**/*.test.ts" | ||||
|   ] | ||||
| } | ||||
|  | ||||
| @ -1176,6 +1176,11 @@ cssstyle@^2.2.0: | ||||
|   dependencies: | ||||
|     cssom "~0.3.6" | ||||
| 
 | ||||
| csv-parse@^4.14.2: | ||||
|   version "4.14.2" | ||||
|   resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.14.2.tgz#c1329cff95a99b8773a92c4e62f8bff114b34726" | ||||
|   integrity sha512-YE2xlTKtM035/94llhgsp9qFQxGi47EkQJ1pZ+mLT/98GpIsbjkMGAb7Rmu9hNxVfYFOLf10hP+rPVqnoccLgw== | ||||
| 
 | ||||
| dashdash@^1.12.0: | ||||
|   version "1.14.1" | ||||
|   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 CrazyMax
						CrazyMax