mirror of
https://github.com/docker/bake-action.git
synced 2026-06-05 09:38:40 +02:00
Compare commits
484 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82490499d2 | |||
| 7017b891b1 | |||
| 8e8fbbb910 | |||
| 471133c110 | |||
| f4a2547f80 | |||
| 04d8281a0b | |||
| 8fdd4fbcfa | |||
| 549b4276f9 | |||
| a22e8b4359 | |||
| 325dda5cc1 | |||
| 124afc9b2a | |||
| 9716e42fa0 | |||
| df378f37f1 | |||
| a47bdde0c3 | |||
| f04bdcca6b | |||
| 80669dec4d | |||
| 7363f027e4 | |||
| 4cde8b2bc2 | |||
| f178d1d921 | |||
| d7926aae53 | |||
| 1e43cd9ec1 | |||
| 6495c30be7 | |||
| cc3dc856a7 | |||
| 261e2f7ede | |||
| 49c12c7536 | |||
| add429de5b | |||
| eeb3544b47 | |||
| e0aed8e67c | |||
| 7366777695 | |||
| a2cea6dea6 | |||
| c77b5b2a1b | |||
| bd4dc5e5a8 | |||
| 836d9ebf26 | |||
| 919640e006 | |||
| 14c7b57f99 | |||
| 7c5fb1ba46 | |||
| 8fb85661a4 | |||
| 0108d7fd26 | |||
| 1cf124c0da | |||
| 244d63bb6d | |||
| 6b5467d611 | |||
| 75c00e7961 | |||
| bf4ef44586 | |||
| a35ee0c096 | |||
| c9a0e8e297 | |||
| ed0758f217 | |||
| 7540d5c95e | |||
| 5be5f02ff8 | |||
| 4f25520e7a | |||
| eeacb3deff | |||
| cce027f633 | |||
| 53ce91f18b | |||
| 6b8437d2b5 | |||
| d14785b0cb | |||
| 597dc07998 | |||
| 8ba51ac4ee | |||
| 23c049fba9 | |||
| 41c10f2beb | |||
| 5b9bf92d49 | |||
| 3acf805d94 | |||
| f6376ff6a4 | |||
| 60b3af61bc | |||
| f08ef55f78 | |||
| c22b3482ed | |||
| 40bffc195e | |||
| d7a0b5eb51 | |||
| 3965f4baf4 | |||
| 3d864c34f9 | |||
| 3589b0c183 | |||
| 2215fae6ab | |||
| d0cb9774dc | |||
| a6c0a91e79 | |||
| 74cb41d332 | |||
| 8f035c08cd | |||
| a4c28defc8 | |||
| d260a27f75 | |||
| 5efdf4de8d | |||
| 1a42865db7 | |||
| ba406cd72e | |||
| 1d0c0ffa52 | |||
| 68cf998b48 | |||
| 7a78e75fa4 | |||
| 24d8c3471c | |||
| 6de75d5ad2 | |||
| 72003b9fac | |||
| a1257e6518 | |||
| 846dea0f3a | |||
| 1367d98caa | |||
| 88f3e5553b | |||
| d576212e5b | |||
| d4a3c3cc87 | |||
| 37816e7475 | |||
| f5304128f3 | |||
| 4318518141 | |||
| 0dc934281a | |||
| 64a5bce7a2 | |||
| 212c367396 | |||
| d1ecc3a41e | |||
| ae6e8fe892 | |||
| 57dcb4dec4 | |||
| 76f9fa3a75 | |||
| 1c2b73661c | |||
| c38fbc0209 | |||
| 9d4c4c70ed | |||
| ab9ee171b4 | |||
| f252d74606 | |||
| 656e858067 | |||
| fdcf61eb1a | |||
| a17047c36c | |||
| 1b9d00da59 | |||
| 8f9e95c9aa | |||
| f7a0604619 | |||
| 4ba453fbc2 | |||
| be887ed69b | |||
| c9725ed6bb | |||
| c1f157cf76 | |||
| 28af3ee8ff | |||
| 4f08b22a19 | |||
| 5c5be5f8ee | |||
| c48383c7fd | |||
| 7bff531c65 | |||
| 4eb699fd94 | |||
| 3310620efe | |||
| 60f5d53310 | |||
| cb84b96ea2 | |||
| 63a0b90c7c | |||
| 5dd4f8e2d6 | |||
| 8342e4814b | |||
| 4e1bb14d4e | |||
| 5a1b7c9786 | |||
| a23a0ceb07 | |||
| 932b78563b | |||
| ded8f8f101 | |||
| d0cc8f345a | |||
| 8afe15ffcc | |||
| 77f4fc97b7 | |||
| bf35764d1d | |||
| 309da7d154 | |||
| 23cff4f49a | |||
| 5ca506d06f | |||
| da6b67e5ed | |||
| 23b87ebfd8 | |||
| f26d1f2c48 | |||
| 3ba2682456 | |||
| d2bf1df12d | |||
| 1677316f88 | |||
| 3fc70e1131 | |||
| f4c177e5d8 | |||
| fb23aa081d | |||
| 4434628f52 | |||
| 289179a60f | |||
| 52e5f5611a | |||
| 95dd0c6749 | |||
| ef35aaaf8b | |||
| a6f037366a | |||
| b6652aadd5 | |||
| fa9f3f5ac7 | |||
| 4c0e3cda9d | |||
| 3883a2154a | |||
| b8df42cc60 | |||
| 9bc07af8a8 | |||
| aeaa6df54c | |||
| 63fc7d13b7 | |||
| fd17cd07cd | |||
| d2a866bfbd | |||
| 1417204e8d | |||
| ef43224233 | |||
| d38ec1b2d6 | |||
| 782be980da | |||
| 51e939be13 | |||
| d5f33222b6 | |||
| 2e3d19baed | |||
| 22815eb8f2 | |||
| c24ab5d426 | |||
| 64673bcfac | |||
| f05b0ee234 | |||
| 6161d12436 | |||
| e626c7390c | |||
| 7e8997e58f | |||
| 9a9d8805d1 | |||
| cdf7e1c5cb | |||
| 01036657a2 | |||
| 76cc8060bd | |||
| 4cfe868c6e | |||
| fa256f8a0c | |||
| 8cea75c238 | |||
| a7cc98928a | |||
| 1b8b2f2b02 | |||
| 955c005d87 | |||
| 4c694667c2 | |||
| bc6f04190c | |||
| 5c57af45fc | |||
| 28c6eb5bfc | |||
| d52034e958 | |||
| 108b34f686 | |||
| af918ef258 | |||
| 1fe547e208 | |||
| 3e6a9c6a82 | |||
| a4d7f0b5b9 | |||
| 1877a04777 | |||
| 6ebd058199 | |||
| eac74531aa | |||
| 4eefc485ba | |||
| b7875ab9fc | |||
| f28b24308f | |||
| ad6ed14e0e | |||
| 93ee8f4f3f | |||
| dbdf67d511 | |||
| 16551d969e | |||
| bfc525280a | |||
| 216ea56fab | |||
| eb0e46e01a | |||
| e14760bd9a | |||
| bc6d272b50 | |||
| c0fe07dad6 | |||
| 9a5de0e159 | |||
| b5bad96092 | |||
| 09e9b54ae9 | |||
| 03ad189f86 | |||
| 3934de3594 | |||
| 2b6f83c616 | |||
| 40a4ea9523 | |||
| b976ed0e11 | |||
| 5060c11b60 | |||
| b0a0aeab0e | |||
| 39fbf35758 | |||
| ff7b24e385 | |||
| fd05574f2b | |||
| 7b24a43e4b | |||
| 10abbd2569 | |||
| 332466b809 | |||
| 867da3c872 | |||
| a06e6ea6d8 | |||
| b4514235a2 | |||
| 455cb06a8b | |||
| 95d04aff03 | |||
| ec3e762834 | |||
| f6acc70fe0 | |||
| f38226533a | |||
| 7e3fb815c2 | |||
| 297b5d570e | |||
| 11ce049f92 | |||
| 47185531a6 | |||
| 1c5f18a523 | |||
| 24721f62e7 | |||
| 7e57eefa1c | |||
| f36da5f84f | |||
| f81e4c23c9 | |||
| 6460b33ba7 | |||
| bc3c21b237 | |||
| 93d1f86e62 | |||
| 00f0c171f7 | |||
| a29d7e9cb9 | |||
| f40a782c97 | |||
| bc96707098 | |||
| 84cc400131 | |||
| 0160c64311 | |||
| 25ba9228c1 | |||
| 69497d5717 | |||
| 2def0425f4 | |||
| 1f186e91c9 | |||
| 8473a36b83 | |||
| bd980ca3d9 | |||
| 1a92fbfaa9 | |||
| 670407c68a | |||
| 4f5d587adf | |||
| a99697dcb6 | |||
| 702752d616 | |||
| 79fe072114 | |||
| 1cc392619e | |||
| 334a1f6c42 | |||
| 5017dd3140 | |||
| 0815d964e4 | |||
| 5a89abed82 | |||
| fdc36b0336 | |||
| 2d78083701 | |||
| b38d33d426 | |||
| fc16f00415 | |||
| 1bc598cbb8 | |||
| 66ac74c2bc | |||
| ea5f9ae401 | |||
| 7361386105 | |||
| ae29a82e5c | |||
| 35800c73fa | |||
| bbeabc29a1 | |||
| c564bf0bb0 | |||
| 6281f4a902 | |||
| 7a5dfed355 | |||
| e2b72bb7a3 | |||
| 27749bcdf3 | |||
| 5f156eafc0 | |||
| b116023d12 | |||
| 2fd7073488 | |||
| 73b0efa7a0 | |||
| 29394f21ba | |||
| 908c98f276 | |||
| b6cc37d5b9 | |||
| dc557970d4 | |||
| 75d6ba252c | |||
| 49c6172f1b | |||
| c2d911883d | |||
| 1a7ee794b9 | |||
| d905335142 | |||
| c8060c064e | |||
| c4a4a41172 | |||
| 8529ef025a | |||
| 9775caf8a9 | |||
| 11d4bbed70 | |||
| 33a1cc61da | |||
| f423d25e3d | |||
| 017aa056d6 | |||
| ac8675748b | |||
| efcacd553e | |||
| 7ea090ddec | |||
| 9c020d87bf | |||
| 2930c788f0 | |||
| 5adcaf655c | |||
| 27bea1331e | |||
| dd824dd722 | |||
| ccc779750c | |||
| 9ef2cc9961 | |||
| b5447a726f | |||
| cd4ed51f40 | |||
| a1e9d9056a | |||
| a36b3d6c7b | |||
| 8ee01addc6 | |||
| fe4533e90f | |||
| 52a1696536 | |||
| 31ed06a2f8 | |||
| 849707117b | |||
| 76293d20bc | |||
| 8af72e0be9 | |||
| 0aeb216f16 | |||
| 286a2006a7 | |||
| b0c3bbe901 | |||
| db7848b641 | |||
| c2495acbad | |||
| 76ed7c5809 | |||
| 063b84c928 | |||
| f14c88d45c | |||
| f9a9d0f498 | |||
| 165199437b | |||
| 098c554ca2 | |||
| 9ceda10db5 | |||
| cff9398622 | |||
| 723de4133f | |||
| 6e0695d43f | |||
| 0ac360076f | |||
| 07a6fa9498 | |||
| 02fc58e41a | |||
| 29640fa79b | |||
| cfc6565e6e | |||
| 13d6925be9 | |||
| d7c9efcb85 | |||
| 04c7b671ff | |||
| 97e2ce4543 | |||
| 511fde2517 | |||
| 78f6bcc0c7 | |||
| 182ac9c10d | |||
| 3529f9f26a | |||
| 3a006c6dda | |||
| fcbf0b54f7 | |||
| d79fe12cbd | |||
| 1b6be708ad | |||
| c21c03ebb4 | |||
| 9a10c7c75c | |||
| e7c069c943 | |||
| 2f1dcd74d6 | |||
| 029c97d421 | |||
| 21b54260ab | |||
| aff6b59653 | |||
| 681d26bef6 | |||
| 2359948f31 | |||
| c3d79c1f33 | |||
| 82d9962996 | |||
| 8570565b5f | |||
| 41f3f77c35 | |||
| d38ae4f644 | |||
| f32fbeac61 | |||
| f081c1d573 | |||
| f0b60add7d | |||
| 674fd7a5cb | |||
| c6d0a7c2e8 | |||
| bcff464424 | |||
| 73fc28eadc | |||
| b587bf2d34 | |||
| d3191ad8da | |||
| f32f8b8d70 | |||
| 16a26530c2 | |||
| 917146eee9 | |||
| b4f450cb7d | |||
| 4cf768c75b | |||
| a841142820 | |||
| aeda4d1cdb | |||
| 445d2b3e0a | |||
| f50c6ab3a8 | |||
| 2891007d0d | |||
| e69738929b | |||
| 2c2cde50c2 | |||
| ad0d2a9712 | |||
| 21bfa47320 | |||
| c47b2ec26c | |||
| 9bcfb28dc6 | |||
| 4c1169b967 | |||
| 90417c5f4e | |||
| 0aa139c0c8 | |||
| e136219da1 | |||
| 39f20cb017 | |||
| 79237baae1 | |||
| 4d50b5c816 | |||
| 794e8fa13e | |||
| 0322b1ba9d | |||
| af2b81ec1f | |||
| 6926262e59 | |||
| d4d5e643fb | |||
| c5f51499a0 | |||
| dc94000d7c | |||
| b5a1ab1e8c | |||
| 6cf674e56b | |||
| 41bb376a43 | |||
| fd09ebd0b9 | |||
| 483bc58234 | |||
| 3f932d0083 | |||
| edc3f2a02e | |||
| 26816e4a1d | |||
| 51ec4ad8f4 | |||
| 9144340090 | |||
| 8d9b8f5e34 | |||
| f96d17d3cb | |||
| d156b88b24 | |||
| d6cd574eb3 | |||
| 209654f2ca | |||
| 134551bf17 | |||
| 667a8e0115 | |||
| 7594aa1931 | |||
| 01a0b5eddc | |||
| 8a5e28c41a | |||
| b2cff86154 | |||
| 7cd078e6ec | |||
| eadc6525c5 | |||
| bee1d8155e | |||
| e6b9522341 | |||
| f845891f5a | |||
| c89ac4a376 | |||
| fcc9bbc659 | |||
| d73a09800c | |||
| 33fe53ec17 | |||
| 6122353776 | |||
| 862a5ef0d5 | |||
| 6c87dcca98 | |||
| 800ee8447d | |||
| a7524f88c3 | |||
| f589b1f80f | |||
| 1c7934bc60 | |||
| 9e746ade7c | |||
| 854dbd7db9 | |||
| 0ddeddfa93 | |||
| b07b164d66 | |||
| 7ee4a98a55 | |||
| 8db227756f | |||
| d7ce3c3dac | |||
| e878ca2dca | |||
| 3123696764 | |||
| c22ea4a824 | |||
| 5cb4f0eeb6 | |||
| e917a42053 | |||
| c7fa0af149 | |||
| 41e0cbc69d | |||
| d6fc753959 | |||
| 7c9d36984e | |||
| 064f6ed0d0 | |||
| d666a2cf09 | |||
| eff809a17c | |||
| bb2d1b0aab | |||
| 438d016327 | |||
| 9e1a3e1d40 | |||
| 4cfa3a6cb8 | |||
| e12a6ceedb | |||
| 7138010b3f | |||
| dbecd73e13 | |||
| 167801e346 | |||
| d125e2ebd4 | |||
| e073915f07 | |||
| 1721b445f7 |
+11
-1
@@ -1,2 +1,12 @@
|
||||
/coverage
|
||||
/node_modules
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es2021": true,
|
||||
"jest/globals": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"jest",
|
||||
"prettier"
|
||||
]
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
/.yarn/releases/** binary
|
||||
/.yarn/plugins/** binary
|
||||
/dist/** linguist-generated=true
|
||||
/lib/** linguist-generated=true
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
* @crazy-max
|
||||
@@ -0,0 +1,3 @@
|
||||
# Code of conduct
|
||||
|
||||
- [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines)
|
||||
@@ -0,0 +1,101 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Bug Report
|
||||
description: Report a bug
|
||||
labels:
|
||||
- status/triage
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to report a bug!
|
||||
If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com).
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Contributing guidelines
|
||||
description: >
|
||||
Make sure you've read the contributing guidelines before proceeding.
|
||||
options:
|
||||
- label: I've read the [contributing guidelines](https://github.com/docker/bake-action/blob/master/.github/CONTRIBUTING.md) and wholeheartedly agree
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "I've found a bug, and:"
|
||||
description: |
|
||||
Make sure that your request fulfills all of the following requirements.
|
||||
If one requirement cannot be satisfied, explain in detail why.
|
||||
options:
|
||||
- label: The documentation does not mention anything about my problem
|
||||
- label: There are no open or closed issues that are related to my problem
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: >
|
||||
Provide a brief description of the bug in 1-2 sentences.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: >
|
||||
Describe precisely what you'd expect to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Actual behaviour
|
||||
description: >
|
||||
Describe precisely what is actually happening.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Repository URL
|
||||
description: >
|
||||
Enter the URL of the repository where you are experiencing the
|
||||
issue. If your repository is private, provide a link to a minimal
|
||||
repository that reproduces the issue.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Workflow run URL
|
||||
description: >
|
||||
Enter the URL of the GitHub Action workflow run if public (e.g.
|
||||
`https://github.com/<user>/<repo>/actions/runs/<id>`)
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: YAML workflow
|
||||
description: |
|
||||
Provide the YAML of the workflow that's causing the issue.
|
||||
Make sure to remove any sensitive information.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Workflow logs
|
||||
description: >
|
||||
[Attach](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files)
|
||||
the [log file of your workflow run](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
|
||||
and make sure to remove any sensitive information.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: BuildKit logs
|
||||
description: >
|
||||
If applicable, provide the [BuildKit container logs](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs)
|
||||
render: text
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: |
|
||||
Provide any additional information that could be useful.
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
---
|
||||
|
||||
### Behaviour
|
||||
|
||||
#### Steps to reproduce this issue
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
#### Expected behaviour
|
||||
|
||||
> Tell us what should happen
|
||||
|
||||
#### Actual behaviour
|
||||
|
||||
> Tell us what happens instead
|
||||
|
||||
### Configuration
|
||||
|
||||
* Repository URL (if public):
|
||||
* Build URL (if public):
|
||||
|
||||
```yml
|
||||
# paste your YAML workflow file here and remove sensitive data
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
> Download the [log file of your build](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
|
||||
> and [attach it](https://docs.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue.
|
||||
@@ -0,0 +1,9 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Questions and Discussions
|
||||
url: https://github.com/docker/bake-action/discussions/new
|
||||
about: Use Github Discussions to ask questions and/or open discussion topics.
|
||||
- name: Documentation
|
||||
url: https://docs.docker.com/build/ci/github-actions/
|
||||
about: Read the documentation.
|
||||
@@ -0,0 +1,15 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Feature request
|
||||
description: Missing functionality? Come tell us about it!
|
||||
labels:
|
||||
- kind/enhancement
|
||||
- status/triage
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: What is the feature you want to see?
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,12 @@
|
||||
# Reporting security issues
|
||||
|
||||
The project maintainers take security seriously. If you discover a security
|
||||
issue, please bring it to their attention right away!
|
||||
|
||||
**Please _DO NOT_ file a public issue**, instead send your report privately to
|
||||
[security@docker.com](mailto:security@docker.com).
|
||||
|
||||
Security reports are greatly appreciated, and we will publicly thank you for it.
|
||||
We also like to send gifts—if you'd like Docker swag, make sure to let
|
||||
us know. We currently do not offer a paid security bounty program, but are not
|
||||
ruling it out in the future.
|
||||
@@ -1,31 +0,0 @@
|
||||
# Support [](https://isitmaintained.com/project/docker/bake-action)
|
||||
|
||||
First, [be a good guy](https://github.com/kossnocorp/etiquette/blob/master/README.md).
|
||||
|
||||
## Reporting an issue
|
||||
|
||||
Please do a search in [open issues](https://github.com/docker/bake-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
|
||||
|
||||
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
|
||||
|
||||
:+1: - upvote
|
||||
|
||||
:-1: - downvote
|
||||
|
||||
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
|
||||
|
||||
## Writing good bug reports and feature requests
|
||||
|
||||
File a single issue per problem and feature request.
|
||||
|
||||
* Do not enumerate multiple bugs or feature requests in the same issue.
|
||||
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
|
||||
|
||||
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
|
||||
|
||||
You are now ready to [create a new issue](https://github.com/docker/bake-action/issues/new/choose)!
|
||||
|
||||
## Closure policy
|
||||
|
||||
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
|
||||
* Issues that go a week without a response from original poster are subject to closure at our discretion.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 253 KiB |
@@ -11,6 +11,7 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
versioning-strategy: "increase"
|
||||
allow:
|
||||
- dependency-type: "production"
|
||||
labels:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,86 @@
|
||||
name: ci-subaction
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 10 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
tags:
|
||||
- 'v*'
|
||||
paths:
|
||||
- '.github/workflows/ci-subaction.yml'
|
||||
- 'subaction/**'
|
||||
- 'test/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/ci-subaction.yml'
|
||||
- 'subaction/**'
|
||||
- 'test/**'
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
-
|
||||
testdir: group
|
||||
expected: >
|
||||
[{"target":"t1"},{"target":"t2"}]
|
||||
-
|
||||
testdir: group-matrix
|
||||
target: validate
|
||||
expected: >
|
||||
[{"target":"lint-default"},{"target":"lint-labs"},{"target":"lint-nydus"},{"target":"lint-proto"},{"target":"lint-yaml"},{"target":"validate-doctoc"},{"target":"validate-vendor"}]
|
||||
-
|
||||
testdir: group-with-platform
|
||||
target: validate
|
||||
expected: >
|
||||
[{"target":"lint"},{"target":"lint-gopls"},{"target":"validate-docs"},{"target":"validate-vendor"}]
|
||||
-
|
||||
testdir: group-with-platform
|
||||
target: validate
|
||||
fields: platforms
|
||||
expected: >
|
||||
[{"target":"lint","platforms":"darwin/amd64"},{"target":"lint","platforms":"darwin/arm64"},{"target":"lint","platforms":"linux/amd64"},{"target":"lint","platforms":"linux/arm64"},{"target":"lint","platforms":"linux/s390x"},{"target":"lint","platforms":"linux/ppc64le"},{"target":"lint","platforms":"linux/riscv64"},{"target":"lint","platforms":"windows/amd64"},{"target":"lint","platforms":"windows/arm64"},{"target":"lint-gopls","platforms":"darwin/amd64"},{"target":"lint-gopls","platforms":"darwin/arm64"},{"target":"lint-gopls","platforms":"linux/amd64"},{"target":"lint-gopls","platforms":"linux/arm64"},{"target":"lint-gopls","platforms":"linux/s390x"},{"target":"lint-gopls","platforms":"linux/ppc64le"},{"target":"lint-gopls","platforms":"linux/riscv64"},{"target":"lint-gopls","platforms":"windows/amd64"},{"target":"lint-gopls","platforms":"windows/arm64"},{"target":"validate-docs"},{"target":"validate-vendor"}]
|
||||
-
|
||||
testdir: group-with-platform
|
||||
target: validate
|
||||
fields: platforms,dockerfile
|
||||
expected: >
|
||||
[{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"darwin/amd64"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"darwin/arm64"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/amd64"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/arm64"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/s390x"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/ppc64le"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/riscv64"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"windows/amd64"},{"target":"lint","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"windows/arm64"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"darwin/amd64"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"darwin/arm64"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/amd64"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/arm64"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/s390x"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/ppc64le"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"linux/riscv64"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"windows/amd64"},{"target":"lint-gopls","dockerfile":"./hack/dockerfiles/lint.Dockerfile","platforms":"windows/arm64"},{"target":"validate-docs","dockerfile":"./hack/dockerfiles/docs.Dockerfile"},{"target":"validate-vendor","dockerfile":"./hack/dockerfiles/vendor.Dockerfile"}]
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Matrix gen
|
||||
id: gen
|
||||
uses: ./subaction/matrix
|
||||
with:
|
||||
workdir: ./test/${{ matrix.testdir }}
|
||||
target: ${{ matrix.target }}
|
||||
fields: ${{ matrix.fields }}
|
||||
-
|
||||
name: Check output
|
||||
uses: actions/github-script@v8
|
||||
env:
|
||||
INPUT_MATRIX: ${{ steps.gen.outputs.matrix }}
|
||||
INPUT_EXPECTED: ${{ matrix.expected }}
|
||||
with:
|
||||
script: |
|
||||
const matrix = JSON.stringify(JSON.parse(core.getInput('matrix')));
|
||||
const expected = JSON.stringify(JSON.parse(core.getInput('expected')));
|
||||
if (matrix !== expected) {
|
||||
throw new Error(`Matrix do not match expected values: ${matrix} != ${expected}`);
|
||||
} else {
|
||||
core.info(`✅`);
|
||||
}
|
||||
+745
-27
@@ -1,18 +1,39 @@
|
||||
name: ci
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
buildx-version:
|
||||
description: 'Buildx version or Git context'
|
||||
default: 'latest'
|
||||
required: false
|
||||
buildkit-image:
|
||||
description: 'BuildKit image'
|
||||
default: 'moby/buildkit:buildx-stable-1'
|
||||
required: false
|
||||
schedule:
|
||||
- cron: '0 10 * * *' # everyday at 10am
|
||||
- cron: '0 10 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
tags:
|
||||
- 'v*'
|
||||
paths-ignore:
|
||||
- '.github/workflows/ci-subaction.yml'
|
||||
- 'subaction/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
paths-ignore:
|
||||
- '.github/workflows/ci-subaction.yml'
|
||||
- 'subaction/**'
|
||||
|
||||
env:
|
||||
BUILDX_VERSION: edge
|
||||
BUILDKIT_IMAGE: moby/buildkit:latest
|
||||
|
||||
jobs:
|
||||
bake:
|
||||
@@ -31,98 +52,795 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v4
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: network=host
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
network=host
|
||||
-
|
||||
name: Build and push
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
files: |
|
||||
./test/config.hcl
|
||||
targets: |
|
||||
${{ matrix.target }}
|
||||
push: false # set to true when https://github.com/docker/buildx/issues/179 is fixed
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
|
||||
error-msg:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
set: |
|
||||
*.platform=linux/amd64,linux/ppc64le,linux/s390x
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
|
||||
error-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Stop docker
|
||||
run: |
|
||||
sudo systemctl stop docker
|
||||
sudo systemctl stop docker docker.socket
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.bake) }}"
|
||||
if [ "${{ steps.bake.outcome }}" != "failure" ] || [ "${{ steps.bake.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
error-source:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
source: ./does-not-exist
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
if [ "${{ steps.bake.outcome }}" != "failure" ] || [ "${{ steps.bake.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
standalone:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Uninstall moby cli
|
||||
name: Uninstall docker cli
|
||||
run: |
|
||||
sudo apt-get purge -y moby-cli moby-buildx
|
||||
if dpkg -s "docker-ce" >/dev/null 2>&1; then
|
||||
sudo dpkg -r --force-depends docker-ce-cli docker-buildx-plugin
|
||||
else
|
||||
sudo apt-get purge -y moby-cli moby-buildx
|
||||
fi
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
|
||||
remote:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: https://github.com/docker/buildx.git#v0.8.2
|
||||
targets: update-docs
|
||||
|
||||
provenance:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
attrs:
|
||||
- ''
|
||||
- mode=max
|
||||
- builder-id=foo
|
||||
- false
|
||||
- true
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test/go
|
||||
targets: binary
|
||||
provenance: ${{ matrix.attrs }}
|
||||
set: |
|
||||
*.output=type=oci,dest=/tmp/build.tar
|
||||
*.cache-from=type=gha,scope=provenance
|
||||
*.cache-to=type=gha,scope=provenance,mode=max
|
||||
|
||||
sbom:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DESTDIR: /tmp/bake-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: image
|
||||
output: type=image,name=localhost:5000/name/app:latest,push=true
|
||||
- target: binary
|
||||
output: /tmp/bake-build
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test/go
|
||||
targets: ${{ matrix.target }}
|
||||
sbom: true
|
||||
set: |
|
||||
*.output=${{ matrix.output }}
|
||||
*.cache-from=type=gha,scope=attests-${{ matrix.target }}
|
||||
*.cache-to=type=gha,scope=attests-${{ matrix.target }},mode=max
|
||||
-
|
||||
name: Inspect image
|
||||
if: matrix.target == 'image'
|
||||
run: |
|
||||
docker buildx imagetools inspect localhost:5000/name/app:latest --format '{{json .}}'
|
||||
-
|
||||
name: Check output folder
|
||||
if: matrix.target == 'binary'
|
||||
working-directory: ${{ env.DESTDIR }}
|
||||
run: |
|
||||
tree .
|
||||
-
|
||||
name: Print provenance
|
||||
if: matrix.target == 'binary'
|
||||
working-directory: ${{ env.DESTDIR }}
|
||||
run: |
|
||||
cat provenance.json | jq
|
||||
-
|
||||
name: Print SBOM
|
||||
if: matrix.target == 'binary'
|
||||
working-directory: ${{ env.DESTDIR }}
|
||||
run: |
|
||||
cat sbom.spdx.json | jq
|
||||
|
||||
set:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test/go
|
||||
set: |
|
||||
*.platform=linux/amd64
|
||||
*.output=type=image,"name=localhost:5000/name/app:v1.0.0,localhost:5000/name/app:latest",push=true
|
||||
*.tags=
|
||||
|
||||
group:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
network=host
|
||||
-
|
||||
name: Build and push
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test/group
|
||||
push: true
|
||||
set: |
|
||||
t1.tags=localhost:5000/name/app:t1
|
||||
t2.tags=localhost:5000/name/app:t2
|
||||
|
||||
docker-config-malformed:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set malformed docker config
|
||||
run: |
|
||||
mkdir -p ~/.docker
|
||||
echo 'foo_bar' >> ~/.docker/config.json
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
|
||||
proxy-docker-config:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
squid-proxy:
|
||||
image: ubuntu/squid:latest
|
||||
ports:
|
||||
- 3128:3128
|
||||
steps:
|
||||
-
|
||||
name: Check proxy
|
||||
run: |
|
||||
netstat -aptn
|
||||
curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy http://127.0.0.1:3128 -v --insecure --head https://www.google.com
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set proxy config
|
||||
run: |
|
||||
mkdir -p ~/.docker
|
||||
echo '{"proxies":{"default":{"httpProxy":"http://127.0.0.1:3128","httpsProxy":"http://127.0.0.1:3128"}}}' > ~/.docker/config.json
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
network=host
|
||||
buildkitd-flags: --debug
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
targets: app-proxy
|
||||
|
||||
proxy-buildkitd:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
squid-proxy:
|
||||
image: ubuntu/squid:latest
|
||||
ports:
|
||||
- 3128:3128
|
||||
steps:
|
||||
-
|
||||
name: Check proxy
|
||||
run: |
|
||||
netstat -aptn
|
||||
curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy http://127.0.0.1:3128 -v --insecure --head https://www.google.com
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
network=host
|
||||
env.http_proxy=http://127.0.0.1:3128
|
||||
env.https_proxy=http://127.0.0.1:3128
|
||||
buildkitd-flags: --debug
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
|
||||
git-context:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
|
||||
git-context-and-local:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
files: |
|
||||
cwd://${{ steps.meta.outputs.bake-file }}
|
||||
|
||||
multi-output:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
network=host
|
||||
-
|
||||
name: Build and push
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test/go
|
||||
set: |
|
||||
*.output=type=image,name=localhost:5000/name/app:latest,push=true
|
||||
*.output=type=docker,name=app:local
|
||||
*.output=type=oci,dest=/tmp/oci.tar
|
||||
-
|
||||
name: Check registry
|
||||
run: |
|
||||
docker buildx imagetools inspect localhost:5000/name/app:latest --format '{{json .}}'
|
||||
-
|
||||
name: Check docker
|
||||
run: |
|
||||
docker image inspect app:local
|
||||
-
|
||||
name: Check oci
|
||||
run: |
|
||||
set -ex
|
||||
mkdir -p /tmp/oci-out
|
||||
tar xf /tmp/oci.tar -C /tmp/oci-out
|
||||
tree -nh /tmp/oci-out
|
||||
|
||||
load-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
network=host
|
||||
-
|
||||
name: Build and push
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test/go
|
||||
targets: image
|
||||
load: true
|
||||
push: true
|
||||
set: |
|
||||
*.tags=localhost:5000/name/app:latest
|
||||
-
|
||||
name: Check registry
|
||||
run: |
|
||||
docker buildx imagetools inspect localhost:5000/name/app:latest --format '{{json .}}'
|
||||
-
|
||||
name: Check docker
|
||||
run: |
|
||||
docker image inspect localhost:5000/name/app:latest
|
||||
|
||||
summary-disable:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
files: |
|
||||
./test/config.hcl
|
||||
targets: app
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
|
||||
summary-not-supported:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: v0.12.1
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
files: |
|
||||
./test/config.hcl
|
||||
targets: app
|
||||
|
||||
record-upload-disable:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
files: |
|
||||
./test/config.hcl
|
||||
targets: app
|
||||
env:
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
record-retention-days:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
days:
|
||||
- 2
|
||||
- 0
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
files: |
|
||||
./test/config.hcl
|
||||
targets: app
|
||||
env:
|
||||
DOCKER_BUILD_RECORD_RETENTION_DAYS: ${{ matrix.days }}
|
||||
|
||||
checks:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
buildx-version:
|
||||
- edge
|
||||
- v0.14.1
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ matrix.buildx-version }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test
|
||||
files: |
|
||||
./lint.hcl
|
||||
|
||||
annotations-disabled:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test
|
||||
files: |
|
||||
./lint.hcl
|
||||
env:
|
||||
DOCKER_BUILD_CHECKS_ANNOTATIONS: false
|
||||
|
||||
allow:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
buildx-version:
|
||||
- edge
|
||||
- v0.19.0
|
||||
- v0.18.0
|
||||
- v0.17.1
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ matrix.buildx-version }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
files: |
|
||||
./test/config.hcl
|
||||
allow: network.host
|
||||
targets: app-entitlements
|
||||
|
||||
no-default-attestations:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
env:
|
||||
BUILDX_NO_DEFAULT_ATTESTATIONS: 1
|
||||
|
||||
call-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test
|
||||
files: |
|
||||
./lint.hcl
|
||||
call: check
|
||||
targets: lint
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
if [ "${{ steps.bake.outcome }}" != "failure" ] || [ "${{ steps.bake.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
call-check-multi:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test
|
||||
files: |
|
||||
./lint.hcl
|
||||
call: check
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
if [ "${{ steps.bake.outcome }}" != "failure" ] || [ "${{ steps.bake.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
call-check-nowarning:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
call: check
|
||||
|
||||
attest-override:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: ./
|
||||
with:
|
||||
source: ./test/attest
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
name: pr-assign-author
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: crazy-max/.github/.github/workflows/pr-assign-author.yml@1b673f36fad86812f538c1df9794904038a23cbf
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
@@ -0,0 +1,21 @@
|
||||
name: publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Publish
|
||||
uses: actions/publish-immutable-action@v0.0.4
|
||||
@@ -1,14 +1,21 @@
|
||||
name: test
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
paths-ignore:
|
||||
- '.github/workflows/ci-subaction.yml'
|
||||
- 'subaction/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
paths-ignore:
|
||||
- '.github/workflows/ci-subaction.yml'
|
||||
- 'subaction/**'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -16,14 +23,16 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v1
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: .
|
||||
targets: test
|
||||
-
|
||||
name: Upload coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
file: ./coverage/clover.xml
|
||||
files: ./coverage/clover.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
name: update-dist
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
update-dist:
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: GitHub auth token from GitHub App
|
||||
id: docker-read-app
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ secrets.GHACTIONS_REPO_WRITE_APP_ID }}
|
||||
private-key: ${{ secrets.GHACTIONS_REPO_WRITE_APP_PRIVATE_KEY }}
|
||||
owner: docker
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.docker-read-app.outputs.token || github.token }}
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: .
|
||||
targets: build
|
||||
-
|
||||
name: Commit and push dist
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||
(
|
||||
set -x
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add dist
|
||||
git commit -m "chore: update generated content"
|
||||
git push
|
||||
)
|
||||
else
|
||||
echo "No changes in dist"
|
||||
fi
|
||||
@@ -1,24 +1,43 @@
|
||||
name: validate
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: List targets
|
||||
id: generate
|
||||
uses: ./subaction/matrix
|
||||
with:
|
||||
target: validate
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
steps:
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v1
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: validate
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
+14
-57
@@ -1,12 +1,5 @@
|
||||
/.dev
|
||||
node_modules
|
||||
lib
|
||||
# https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
|
||||
# Jetbrains
|
||||
/.idea
|
||||
/*.iml
|
||||
|
||||
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
@@ -14,6 +7,7 @@ npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
@@ -24,34 +18,14 @@ pids
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
@@ -61,36 +35,19 @@ typings/
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.test
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/
|
||||
+1
-2
@@ -6,6 +6,5 @@
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
# https://yarnpkg.com/configuration/yarnrc
|
||||
|
||||
compressionLevel: mixed
|
||||
enableGlobalCache: false
|
||||
enableHardenedMode: true
|
||||
|
||||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
- code: YN0019
|
||||
level: discard
|
||||
- code: YN0076
|
||||
level: discard
|
||||
- code: YN0086
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
@@ -1,17 +1,12 @@
|
||||
[](https://github.com/docker/bake-action/releases/latest)
|
||||
[](https://github.com/marketplace/actions/docker-buildx-bake)
|
||||
[](https://github.com/docker/bake-action/actions?workflow=test)
|
||||
[](https://github.com/docker/bake-action/actions?workflow=ci)
|
||||
[](https://github.com/docker/bake-action/actions?workflow=test)
|
||||
[](https://codecov.io/gh/docker/bake-action)
|
||||
|
||||
## :test_tube: Experimental
|
||||
|
||||
This repository is considered **EXPERIMENTAL** and under active development until further notice. It is subject to
|
||||
non-backward compatible changes or removal in any future version so you should [pin to a specific tag/commit](https://docs.github.com/en/actions/creating-actions/about-actions#using-tags-for-release-management)
|
||||
of this action in your workflow (i.e `docker/bake-action@v1.1.3`).
|
||||
|
||||
## About
|
||||
|
||||
GitHub Action to use Docker [Buildx Bake](https://github.com/docker/buildx/blob/master/docs/reference/buildx_bake.md)
|
||||
GitHub Action to use Docker [Buildx Bake](https://docs.docker.com/build/customize/bake/)
|
||||
as a high-level build command.
|
||||
|
||||

|
||||
@@ -19,20 +14,110 @@ as a high-level build command.
|
||||
___
|
||||
|
||||
* [Usage](#usage)
|
||||
* [Git context](#git-context)
|
||||
* [Path context](#path-context)
|
||||
* [Summaries](#summaries)
|
||||
* [Customizing](#customizing)
|
||||
* [inputs](#inputs)
|
||||
* [outputs](#outputs)
|
||||
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
|
||||
* [environment variables](#environment-variables)
|
||||
* [Subactions](#subactions)
|
||||
* [`matrix`](subaction/matrix)
|
||||
* [Notes](#notes)
|
||||
* [Source semantics](#source-semantics)
|
||||
* [Contributing](#contributing)
|
||||
|
||||
## Usage
|
||||
|
||||
### Git context
|
||||
|
||||
Since `v6` this action uses the [Git context](https://docs.docker.com/build/bake/remote-definition/)
|
||||
to build from a remote bake definition by default like the [build-push-action](https://github.com/docker/build-push-action)
|
||||
does. This means that you don't need to use the [`actions/checkout`](https://github.com/actions/checkout/)
|
||||
action to check out the repository as [BuildKit](https://docs.docker.com/build/buildkit/)
|
||||
will do this directly.
|
||||
|
||||
The git reference will be based on the [event that triggered your workflow](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows)
|
||||
and will result in the following context: `https://github.com/<owner>/<repo>.git#<ref>`.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
bake:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
push: true
|
||||
set: |
|
||||
*.tags=user/app:latest
|
||||
```
|
||||
|
||||
Be careful because **any file mutation in the steps that precede the build step
|
||||
will be ignored, including processing of the `.dockerignore` file** since
|
||||
the context is based on the Git reference. However, you can use the
|
||||
[Path context](#path-context) using the [`source` input](#inputs) alongside
|
||||
the [`actions/checkout`](https://github.com/actions/checkout/) action to remove
|
||||
this restriction.
|
||||
|
||||
Default Git context can also be provided using the [Handlebars template](https://handlebarsjs.com/guide/)
|
||||
expression `{{defaultContext}}`. Here we can use it to provide a subdirectory
|
||||
to the default Git context:
|
||||
|
||||
```yaml
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: "{{defaultContext}}:mysubdir"
|
||||
push: true
|
||||
set: |
|
||||
*.tags=user/app:latest
|
||||
```
|
||||
|
||||
Building from the current repository automatically uses the `GITHUB_TOKEN`
|
||||
secret that GitHub [automatically creates for workflows](https://docs.github.com/en/actions/security-guides/automatic-token-authentication),
|
||||
so you don't need to pass that manually. If you want to authenticate against
|
||||
another private repository for remote definitions, you can set the
|
||||
[`BUILDX_BAKE_GIT_AUTH_TOKEN` environment variable](https://docs.docker.com/build/building/variables/#buildx_bake_git_auth_token).
|
||||
|
||||
> [!NOTE]
|
||||
> Supported since Buildx 0.14.0
|
||||
|
||||
```yaml
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
push: true
|
||||
set: |
|
||||
*.tags=user/app:latest
|
||||
env:
|
||||
BUILDX_BAKE_GIT_AUTH_TOKEN: ${{ secrets.MYTOKEN }}
|
||||
```
|
||||
|
||||
### Path context
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
bake:
|
||||
@@ -40,28 +125,89 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/bake-action@master
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: .
|
||||
push: true
|
||||
set: |
|
||||
*.tags=user/app:latest
|
||||
```
|
||||
|
||||
If you point `source` to a subdirectory, relative paths are resolved from that
|
||||
subdirectory:
|
||||
|
||||
```yaml
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: ./subdir
|
||||
files: ./docker-bake.hcl
|
||||
```
|
||||
|
||||
For example, if `./subdir/docker-bake.hcl` contains:
|
||||
|
||||
```hcl
|
||||
target "default" {
|
||||
output = ["type=local,dest=./artifacts"]
|
||||
}
|
||||
```
|
||||
|
||||
The output will be written to `./subdir/artifacts` in the workspace.
|
||||
|
||||
> [!NOTE]
|
||||
> More info about `source` semantics in the [Source semantics](#source-semantics) section.
|
||||
|
||||
## Summaries
|
||||
|
||||
This action generates a [job summary](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/)
|
||||
that provides a detailed overview of the build execution. The summary shows an
|
||||
overview of all the steps executed during the build, including the build
|
||||
inputs, bake definition, and eventual errors.
|
||||
|
||||

|
||||
|
||||
The summary also includes a link for downloading a build record archive with
|
||||
additional details about the build execution for all the bake targets,
|
||||
including build stats, logs, outputs, and more. The build record can be
|
||||
imported to Docker Desktop for inspecting the build in greater detail.
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> If you're using the [`actions/download-artifact`](https://github.com/actions/download-artifact)
|
||||
> action in your workflow, you need to ignore the build record artifacts
|
||||
> if `name` and `pattern` inputs are not specified ([defaults to download all artifacts](https://github.com/actions/download-artifact?tab=readme-ov-file#download-all-artifacts) of the workflow),
|
||||
> otherwise the action will fail:
|
||||
> ```yaml
|
||||
> - uses: actions/download-artifact@v4
|
||||
> with:
|
||||
> pattern: "!*.dockerbuild"
|
||||
> ```
|
||||
> More info: https://github.com/actions/toolkit/pull/1874
|
||||
|
||||
Summaries are enabled by default, but can be disabled with the
|
||||
`DOCKER_BUILD_SUMMARY` [environment variable](#environment-variables).
|
||||
|
||||
For more information about summaries, refer to the
|
||||
[documentation](https://docs.docker.com/go/build-summary/).
|
||||
|
||||
## Customizing
|
||||
|
||||
### inputs
|
||||
|
||||
Following inputs can be used as `step.with` keys
|
||||
The following inputs can be used as `step.with` keys
|
||||
|
||||
> `List` type is a newline-delimited string
|
||||
> ```yaml
|
||||
@@ -78,37 +224,62 @@ Following inputs can be used as `step.with` keys
|
||||
> targets: default,release
|
||||
> ```
|
||||
|
||||
| Name | Type | Description |
|
||||
|------------------|----------|------------------------------------|
|
||||
| `builder` | String | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
|
||||
| `files` | List/CSV | List of [bake definition files](https://github.com/docker/buildx/blob/master/docs/reference/buildx_bake.md#file) |
|
||||
| `targets` | List/CSV | List of bake targets |
|
||||
| `no-cache` | Bool | Do not use cache when building the image (default `false`) |
|
||||
| `pull` | Bool | Always attempt to pull a newer version of the image (default `false`) |
|
||||
| `load` | Bool | Load is a shorthand for `--set=*.output=type=docker` (default `false`) |
|
||||
| `push` | Bool | Push is a shorthand for `--set=*.output=type=registry` (default `false`) |
|
||||
| `set` | List | List of [targets values to override](https://github.com/docker/buildx/blob/master/docs/reference/buildx_bake.md#set) (eg: `targetpattern.key=value`) |
|
||||
| Name | Type | Description |
|
||||
|----------------|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `builder` | String | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
|
||||
| `allow` | List/CSV | Allow build to access specified resources (e.g., `network.host`) |
|
||||
| `call` | String | Set method for evaluating build (e.g., check) |
|
||||
| `files` | List/CSV | List of [bake definition files](https://docs.docker.com/build/customize/bake/file-definition/) |
|
||||
| `no-cache` | Bool | Do not use cache when building the image (default `false`) |
|
||||
| `pull` | Bool | Always attempt to pull a newer version of the image (default `false`) |
|
||||
| `load` | Bool | Load is a shorthand for `--set=*.output=type=docker` (default `false`) |
|
||||
| `provenance` | Bool/String | [Provenance](https://docs.docker.com/build/attestations/slsa-provenance/) is a shorthand for `--set=*.attest=type=provenance` |
|
||||
| `push` | Bool | Push is a shorthand for `--set=*.output=type=registry` (default `false`) |
|
||||
| `sbom` | Bool/String | [SBOM](https://docs.docker.com/build/attestations/sbom/) is a shorthand for `--set=*.attest=type=sbom` |
|
||||
| `set` | List | List of [targets values to override](https://docs.docker.com/engine/reference/commandline/buildx_bake/#set) (e.g., `targetpattern.key=value`) |
|
||||
| `source` | String | Build source to use. Supports local path and [remote bake definition](https://docs.docker.com/build/bake/remote-definition/). With a local path, Bake runs from that directory, so all relative paths are resolved from it. See [Source semantics](#source-semantics). |
|
||||
| `targets` | List/CSV | List of bake targets (`default` target used if empty) |
|
||||
| `github-token` | String | API token used to authenticate to a Git repository for [remote definitions](https://docs.docker.com/build/bake/remote-definition/) (default `${{ github.token }}`) |
|
||||
|
||||
### outputs
|
||||
|
||||
Following outputs are available
|
||||
The following outputs are available
|
||||
|
||||
| Name | Type | Description |
|
||||
|-------------------|---------|---------------------------------------|
|
||||
| `metadata` | JSON | Build result metadata |
|
||||
| Name | Type | Description |
|
||||
|------------|------|-----------------------|
|
||||
| `metadata` | JSON | Build result metadata |
|
||||
|
||||
## Keep up-to-date with GitHub Dependabot
|
||||
### environment variables
|
||||
|
||||
Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot)
|
||||
has [native GitHub Actions support](https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem),
|
||||
to enable it on your GitHub repo all you need to do is add the `.github/dependabot.yml` file:
|
||||
| Name | Type | Default | Description |
|
||||
|--------------------------------------|--------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `DOCKER_BUILD_CHECKS_ANNOTATIONS` | Bool | `true` | If `false`, GitHub annotations are not generated for [build checks](https://docs.docker.com/build/checks/) |
|
||||
| `DOCKER_BUILD_SUMMARY` | Bool | `true` | If `false`, [build summary](https://docs.docker.com/build/ci/github-actions/build-summary/) generation is disabled |
|
||||
| `DOCKER_BUILD_RECORD_UPLOAD` | Bool | `true` | If `false`, build record upload as [GitHub artifact](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts) is disabled |
|
||||
| `DOCKER_BUILD_RECORD_RETENTION_DAYS` | Number | | Duration after which build record artifact will expire in days. Defaults to repository/org [retention settings](https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration#artifact-and-log-retention-policy) if unset or `0` |
|
||||
|
||||
```yaml
|
||||
version: 2
|
||||
updates:
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
```
|
||||
## Subactions
|
||||
|
||||
* [`matrix`](subaction/matrix)
|
||||
|
||||
## Notes
|
||||
|
||||
### Source semantics
|
||||
|
||||
`source` accepts either a Git/remote bake definition (for example `{{defaultContext}}` or `{{defaultContext}}:subdir`)
|
||||
or a local path (for example `.` or `./subdir`). When `source` is a local path,
|
||||
the action runs Bake from that directory (equivalent to `cd <path> && docker buildx bake`).
|
||||
|
||||
This local path mode affects all relative paths resolved by Bake, not only
|
||||
target `context` fields. This includes paths used by local outputs, cache
|
||||
import/export, and `cwd://` references.
|
||||
|
||||
| `source` | Behavior |
|
||||
|-----------------------------------------------------------------------|------------------------------------------------------------------------------------------------|
|
||||
| Git/remote (`{{defaultContext}}`, `https://...git#ref`, `...:subdir`) | Uses [remote bake definition](https://docs.docker.com/build/bake/remote-definition/) behavior. |
|
||||
| Local path (`.`, `./subdir`) | Changes Bake working directory to that path before invoking Bake. |
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to contribute? Awesome! You can find information about contributing to
|
||||
this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md)
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
import {describe, expect, it, jest, test} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as buildx from '../src/buildx';
|
||||
import * as context from '../src/context';
|
||||
|
||||
const tmpNameSync = path.join('/tmp/.docker-bake-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||
const metadata = `{
|
||||
"containerimage.config.digest": "sha256:059b68a595b22564a1cbc167af369349fdc2ecc1f7bc092c2235cbf601a795fd",
|
||||
"containerimage.digest": "sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c"
|
||||
}`;
|
||||
|
||||
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||
const tmpDir = path.join('/tmp/.docker-bake-jest').split(path.sep).join(path.posix.sep);
|
||||
if (!fs.existsSync(tmpDir)) {
|
||||
fs.mkdirSync(tmpDir, {recursive: true});
|
||||
}
|
||||
return tmpDir;
|
||||
});
|
||||
|
||||
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||
return tmpNameSync;
|
||||
});
|
||||
|
||||
describe('getMetadata', () => {
|
||||
it('matches', async () => {
|
||||
const metadataFile = await buildx.getMetadataFile();
|
||||
await fs.writeFileSync(metadataFile, metadata);
|
||||
const expected = await buildx.getMetadata();
|
||||
expect(expected).toEqual(metadata);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAvailable', () => {
|
||||
const execSpy = jest.spyOn(exec, 'getExecOutput');
|
||||
buildx.isAvailable();
|
||||
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAvailable standalone', () => {
|
||||
const execSpy = jest.spyOn(exec, 'getExecOutput');
|
||||
buildx.isAvailable(true);
|
||||
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(execSpy).toHaveBeenCalledWith(`buildx`, [], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVersion', () => {
|
||||
it('valid', async () => {
|
||||
const version = await buildx.getVersion();
|
||||
expect(semver.valid(version)).not.toBeNull();
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('parseVersion', () => {
|
||||
test.each([
|
||||
['github.com/docker/buildx 0.4.1+azure bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
|
||||
['github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
|
||||
['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'],
|
||||
['github.com/docker/buildx f117971 f11797113e5a9b86bd976329c5dbb8a8bfdfadfa', 'f117971']
|
||||
])('given %p', async (stdout, expected) => {
|
||||
expect(buildx.parseVersion(stdout)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
+368
-168
@@ -1,176 +1,384 @@
|
||||
import {beforeEach, describe, expect, it, jest} from '@jest/globals';
|
||||
import {afterEach, beforeEach, describe, expect, test, vi} from 'vitest';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as context from '../src/context';
|
||||
import * as path from 'path';
|
||||
|
||||
describe('getInputList', () => {
|
||||
it('single line correctly', async () => {
|
||||
await setInput('foo', 'bar');
|
||||
const res = context.getInputList('foo');
|
||||
expect(res).toEqual(['bar']);
|
||||
});
|
||||
import {Bake} from '@docker/actions-toolkit/lib/buildx/bake.js';
|
||||
import {Builder} from '@docker/actions-toolkit/lib/buildx/builder.js';
|
||||
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx.js';
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker.js';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
|
||||
|
||||
it('multiline correctly', async () => {
|
||||
setInput('foo', 'bar\nbaz');
|
||||
const res = context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
import {BakeDefinition} from '@docker/actions-toolkit/lib/types/buildx/bake.js';
|
||||
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder.js';
|
||||
|
||||
it('empty lines correctly', async () => {
|
||||
setInput('foo', 'bar\n\nbaz');
|
||||
const res = context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
import * as context from '../src/context.js';
|
||||
|
||||
it('comma correctly', async () => {
|
||||
setInput('foo', 'bar,baz');
|
||||
const res = context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'context-'));
|
||||
const fixturesDir = path.join(__dirname, 'fixtures');
|
||||
|
||||
it('empty result correctly', async () => {
|
||||
setInput('foo', 'bar,baz,');
|
||||
const res = context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('different new lines correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz');
|
||||
const res = context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('different new lines and comma correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz,bat');
|
||||
const res = context.getInputList('foo');
|
||||
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 = context.getInputList('cache-from', true);
|
||||
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 = context.getInputList('cache-from', true);
|
||||
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 = context.getInputList('secrets', true);
|
||||
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 = context.getInputList('secrets', true);
|
||||
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 = context.getInputList('secrets', true);
|
||||
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 = context.getInputList('secrets', true);
|
||||
expect(res).toEqual([
|
||||
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
|
||||
`MYSECRET=aaaaaaaa
|
||||
bbbb"bbb
|
||||
ccccccccc`,
|
||||
'FOO=bar'
|
||||
]);
|
||||
});
|
||||
vi.spyOn(Docker, 'isAvailable').mockImplementation(async (): Promise<boolean> => {
|
||||
return true;
|
||||
});
|
||||
|
||||
describe('asyncForEach', () => {
|
||||
it('executes async tasks sequentially', async () => {
|
||||
const testValues = [1, 2, 3, 4, 5];
|
||||
const results: number[] = [];
|
||||
|
||||
await context.asyncForEach(testValues, async value => {
|
||||
results.push(value);
|
||||
});
|
||||
|
||||
expect(results).toEqual(testValues);
|
||||
});
|
||||
const metadataJson = path.join(tmpDir, 'metadata.json');
|
||||
vi.spyOn(Bake.prototype, 'getMetadataFilePath').mockImplementation((): string => {
|
||||
return metadataJson;
|
||||
});
|
||||
|
||||
describe('setOutput', () => {
|
||||
type BuilderInfoFixture = Omit<BuilderInfo, 'lastActivity'> & {lastActivity: string};
|
||||
const builderInfoFixture = <BuilderInfoFixture>JSON.parse(fs.readFileSync(path.join(fixturesDir, 'builder-info.json'), {encoding: 'utf-8'}).trim());
|
||||
vi.spyOn(Builder.prototype, 'inspect').mockImplementation(async (): Promise<BuilderInfo> => {
|
||||
return {
|
||||
...builderInfoFixture,
|
||||
lastActivity: new Date(builderInfoFixture.lastActivity)
|
||||
};
|
||||
});
|
||||
|
||||
vi.spyOn(Bake.prototype, 'getDefinition').mockImplementation(async (): Promise<BakeDefinition> => {
|
||||
return <BakeDefinition>JSON.parse(fs.readFileSync(path.join(fixturesDir, 'bake-def.json'), {encoding: 'utf-8'}).trim());
|
||||
});
|
||||
|
||||
describe('getArgs', () => {
|
||||
const originalEnv = process.env;
|
||||
beforeEach(() => {
|
||||
process.stdout.write = jest.fn() as typeof process.stdout.write;
|
||||
process.env = Object.keys(process.env).reduce((object, key) => {
|
||||
if (!key.startsWith('INPUT_')) {
|
||||
object[key] = process.env[key];
|
||||
}
|
||||
return object;
|
||||
}, {});
|
||||
});
|
||||
afterEach(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line jest/expect-expect
|
||||
it('setOutput produces the correct command', () => {
|
||||
context.setOutput('some output', 'some value');
|
||||
assertWriteCalls([`::set-output name=some output::some value${os.EOL}`]);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line jest/expect-expect
|
||||
it('setOutput handles bools', () => {
|
||||
context.setOutput('some output', false);
|
||||
assertWriteCalls([`::set-output name=some output::false${os.EOL}`]);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line jest/expect-expect
|
||||
it('setOutput handles numbers', () => {
|
||||
context.setOutput('some output', 1.01);
|
||||
assertWriteCalls([`::set-output name=some output::1.01${os.EOL}`]);
|
||||
});
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
0,
|
||||
'0.4.1',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
1,
|
||||
'0.8.2',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false']
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
2,
|
||||
'0.8.2',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['targets', 'webapp\nvalidate'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false']
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson,
|
||||
'webapp', 'validate'
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
3,
|
||||
'0.8.2',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['set', '*.cache-from=type=gha\n*.cache-to=type=gha'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false']
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--set', '*.cache-from=type=gha',
|
||||
'--set', '*.cache-to=type=gha',
|
||||
'--metadata-file', metadataJson
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
4,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
5,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['provenance', 'true'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson,
|
||||
"--provenance", `builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
6,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['provenance', 'mode=max'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson,
|
||||
"--provenance", `mode=max,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
7,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['provenance', 'false'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson,
|
||||
"--provenance", 'false'
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
8,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['provenance', 'builder-id=foo'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson,
|
||||
"--provenance", 'builder-id=foo'
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
9,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['set', `*.platform=linux/amd64,linux/ppc64le,linux/s390x\n*.output=type=image,"name=moby/buildkit:v0.11.0,moby/buildkit:latest",push=true`],
|
||||
['targets', `"image-all"`],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--set', '*.platform=linux/amd64,linux/ppc64le,linux/s390x',
|
||||
'--set', `*.output=type=image,"name=moby/buildkit:v0.11.0,moby/buildkit:latest",push=true`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'image-all'
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
10,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['set', `*.labels.foo=bar=#baz`],
|
||||
['targets', `"image-all"`],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--set', `*.labels.foo=bar=#baz`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'image-all'
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
11,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['files', './foo.hcl'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'https://github.com/docker/bake-action.git#refs/heads/master',
|
||||
'--file', './foo.hcl',
|
||||
'--metadata-file', metadataJson,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
12,
|
||||
'0.17.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['allow', 'network.host'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--allow', 'network.host',
|
||||
'--metadata-file', metadataJson,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
13,
|
||||
'0.15.0',
|
||||
new Map<string, string>([
|
||||
['source', '{{defaultContext}}:subdir'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['files', './foo.hcl'],
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'https://github.com/docker/bake-action.git#refs/heads/master:subdir',
|
||||
'--file', './foo.hcl',
|
||||
'--metadata-file', metadataJson,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/bake-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
[
|
||||
14,
|
||||
'0.15.0',
|
||||
new Map<string, string>([
|
||||
['source', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false']
|
||||
]),
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson
|
||||
],
|
||||
new Map<string, string>([
|
||||
['BUILDX_NO_DEFAULT_ATTESTATIONS', '1']
|
||||
])
|
||||
],
|
||||
])(
|
||||
'[%d] given %o with %o as inputs, returns %o',
|
||||
async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>, envs: Map<string, string> | undefined) => {
|
||||
if (envs) {
|
||||
envs.forEach((value: string, name: string) => {
|
||||
process.env[name] = value;
|
||||
});
|
||||
}
|
||||
inputs.forEach((value: string, name: string) => {
|
||||
setInput(name, value);
|
||||
});
|
||||
const toolkit = new Toolkit();
|
||||
vi.spyOn(Buildx.prototype, 'version').mockImplementation(async (): Promise<string> => {
|
||||
return buildxVersion;
|
||||
});
|
||||
const inp = await context.getInputs();
|
||||
const definition = await toolkit.buildxBake.getDefinition(
|
||||
{
|
||||
files: inp.files,
|
||||
load: inp.load,
|
||||
noCache: inp['no-cache'],
|
||||
overrides: inp.set,
|
||||
provenance: inp.provenance,
|
||||
push: inp.push,
|
||||
sbom: inp.sbom,
|
||||
source: inp.source.remoteRef,
|
||||
targets: inp.targets
|
||||
},
|
||||
{
|
||||
cwd: inp.source.workdir,
|
||||
}
|
||||
);
|
||||
const res = await context.getArgs(inp, definition, toolkit);
|
||||
expect(res).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// See: https://github.com/actions/toolkit/blob/a1b068ec31a042ff1e10a522d8fdf0b8869d53ca/packages/core/src/core.ts#L89
|
||||
@@ -181,11 +389,3 @@ function getInputName(name: string): string {
|
||||
function setInput(name: string, value: string): void {
|
||||
process.env[getInputName(name)] = value;
|
||||
}
|
||||
|
||||
// Assert that process.stdout.write calls called only with the given arguments.
|
||||
function assertWriteCalls(calls: string[]): void {
|
||||
expect(process.stdout.write).toHaveBeenCalledTimes(calls.length);
|
||||
for (let i = 0; i < calls.length; i++) {
|
||||
expect(process.stdout.write).toHaveBeenNthCalledWith(i + 1, calls[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import {describe, expect, it, jest} from '@jest/globals';
|
||||
import * as docker from '../src/docker';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
describe('isAvailable', () => {
|
||||
it('cli', () => {
|
||||
const execSpy = jest.spyOn(exec, 'getExecOutput');
|
||||
docker.isAvailable();
|
||||
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(execSpy).toHaveBeenCalledWith(`docker`, undefined, {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"group": {
|
||||
"default": {
|
||||
"targets": [
|
||||
"validate"
|
||||
]
|
||||
},
|
||||
"validate": {
|
||||
"targets": [
|
||||
"lint",
|
||||
"validate-vendor",
|
||||
"validate-docs"
|
||||
]
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"lint": {
|
||||
"context": ".",
|
||||
"dockerfile": "./hack/dockerfiles/lint.Dockerfile",
|
||||
"args": {
|
||||
"BUILDKIT_CONTEXT_KEEP_GIT_DIR": "1",
|
||||
"GO_VERSION": "1.20"
|
||||
},
|
||||
"output": [
|
||||
"type=cacheonly"
|
||||
]
|
||||
},
|
||||
"validate-docs": {
|
||||
"context": ".",
|
||||
"dockerfile": "./hack/dockerfiles/docs.Dockerfile",
|
||||
"args": {
|
||||
"BUILDKIT_CONTEXT_KEEP_GIT_DIR": "1",
|
||||
"BUILDX_EXPERIMENTAL": "1",
|
||||
"FORMATS": "md",
|
||||
"GO_VERSION": "1.20"
|
||||
},
|
||||
"target": "validate",
|
||||
"output": [
|
||||
"type=cacheonly"
|
||||
]
|
||||
},
|
||||
"validate-vendor": {
|
||||
"context": ".",
|
||||
"dockerfile": "./hack/dockerfiles/vendor.Dockerfile",
|
||||
"args": {
|
||||
"BUILDKIT_CONTEXT_KEEP_GIT_DIR": "1",
|
||||
"GO_VERSION": "1.20"
|
||||
},
|
||||
"target": "validate",
|
||||
"output": [
|
||||
"type=cacheonly"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "builder2",
|
||||
"driver": "docker-container",
|
||||
"lastActivity": "2023-01-16 09:45:23 +0000 UTC",
|
||||
"nodes": [
|
||||
{
|
||||
"buildkit": "v0.11.0",
|
||||
"buildkitd-flags": "--debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
|
||||
"driver-opts": [
|
||||
"BUILDKIT_STEP_LOG_MAX_SIZE=10485760",
|
||||
"BUILDKIT_STEP_LOG_MAX_SPEED=10485760",
|
||||
"JAEGER_TRACE=localhost:6831",
|
||||
"image=moby/buildkit:latest",
|
||||
"network=host"
|
||||
],
|
||||
"endpoint": "unix:///var/run/docker.sock",
|
||||
"name": "builder20",
|
||||
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6",
|
||||
"status": "running"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import {vi} from 'vitest';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-bake-action-'));
|
||||
|
||||
const githubPayload = {
|
||||
repository: {
|
||||
private: true
|
||||
}
|
||||
};
|
||||
|
||||
const githubEventPath = path.join(tmpDir, 'github-event.json');
|
||||
fs.writeFileSync(githubEventPath, JSON.stringify(githubPayload));
|
||||
|
||||
process.env = Object.assign({}, process.env, {
|
||||
TEMP: tmpDir,
|
||||
GITHUB_REPOSITORY: 'docker/bake-action',
|
||||
GITHUB_REF: 'refs/heads/master',
|
||||
GITHUB_RUN_ID: '123456789',
|
||||
GITHUB_RUN_ATTEMPT: '1',
|
||||
GITHUB_EVENT_PATH: githubEventPath,
|
||||
RUNNER_TEMP: path.join(tmpDir, 'runner-temp'),
|
||||
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache')
|
||||
});
|
||||
|
||||
vi.mock('@actions/github', () => ({
|
||||
context: {
|
||||
repo: {
|
||||
owner: 'docker',
|
||||
repo: 'bake-action'
|
||||
},
|
||||
ref: 'refs/heads/master',
|
||||
runId: 123456789,
|
||||
payload: githubPayload
|
||||
},
|
||||
getOctokit: vi.fn()
|
||||
}));
|
||||
+24
-4
@@ -10,11 +10,14 @@ inputs:
|
||||
builder:
|
||||
description: "Builder instance"
|
||||
required: false
|
||||
allow:
|
||||
description: "Allow build to access specified resources (e.g., network.host)"
|
||||
required: false
|
||||
call:
|
||||
description: "Set method for evaluating build (e.g., check)"
|
||||
required: false
|
||||
files:
|
||||
description: "List of bake definition files"
|
||||
required: true
|
||||
targets:
|
||||
description: "List of bake targets"
|
||||
required: false
|
||||
no-cache:
|
||||
description: "Do not use cache when building the image"
|
||||
@@ -28,18 +31,35 @@ inputs:
|
||||
description: "Load is a shorthand for --set=*.output=type=docker"
|
||||
required: false
|
||||
default: 'false'
|
||||
provenance:
|
||||
description: "Provenance is a shorthand for --set=*.attest=type=provenance"
|
||||
required: false
|
||||
push:
|
||||
description: "Push is a shorthand for --set=*.output=type=registry"
|
||||
required: false
|
||||
default: 'false'
|
||||
sbom:
|
||||
description: "SBOM is a shorthand for --set=*.attest=type=sbom"
|
||||
required: false
|
||||
set:
|
||||
description: "List of targets values to override (eg. targetpattern.key=value)"
|
||||
required: false
|
||||
source:
|
||||
description: "Context to build from. Can be either local to specify the working directory or a remote bake definition"
|
||||
required: false
|
||||
targets:
|
||||
description: "List of bake targets"
|
||||
required: false
|
||||
github-token:
|
||||
description: "API token used to authenticate to a Git repository for remote definitions"
|
||||
default: ${{ github.token }}
|
||||
required: false
|
||||
|
||||
outputs:
|
||||
metadata:
|
||||
description: 'Build result metadata'
|
||||
|
||||
runs:
|
||||
using: 'node16'
|
||||
using: 'node24'
|
||||
main: 'dist/index.js'
|
||||
post: 'dist/index.js'
|
||||
|
||||
+45
-34
@@ -1,15 +1,21 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG NODE_VERSION=16
|
||||
ARG DOCKER_VERSION=20.10.13
|
||||
ARG BUILDX_VERSION=0.8.1
|
||||
ARG NODE_VERSION=24
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS base
|
||||
RUN apk add --no-cache cpio findutils git
|
||||
RUN apk add --no-cache cpio findutils git rsync
|
||||
WORKDIR /src
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache <<EOT
|
||||
set -e
|
||||
corepack enable
|
||||
yarn --version
|
||||
yarn config set --home enableTelemetry 0
|
||||
EOT
|
||||
|
||||
FROM base AS deps
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn install && mkdir /vendor && cp yarn.lock /vendor
|
||||
|
||||
@@ -18,61 +24,66 @@ COPY --from=deps /vendor /
|
||||
|
||||
FROM deps AS vendor-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"'
|
||||
git status --porcelain -- yarn.lock
|
||||
exit 1
|
||||
fi
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"'
|
||||
git status --porcelain -- yarn.lock
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS build
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run build && mkdir /out && cp -Rf dist /out/
|
||||
RUN --mount=target=/context \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules <<EOT
|
||||
set -e
|
||||
rsync -a /context/. .
|
||||
rm -rf dist
|
||||
yarn run build
|
||||
mkdir /out
|
||||
cp -r dist /out
|
||||
EOT
|
||||
|
||||
FROM scratch AS build-update
|
||||
COPY --from=build /out /
|
||||
|
||||
FROM build AS build-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /out/* .
|
||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
|
||||
git status --porcelain -- dist
|
||||
exit 1
|
||||
fi
|
||||
RUN --mount=target=/context \
|
||||
--mount=target=.,type=tmpfs <<EOT
|
||||
set -e
|
||||
rsync -a /context/. .
|
||||
git add -A
|
||||
rm -rf dist
|
||||
cp -rf /out/* .
|
||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
|
||||
git status --porcelain -- dist
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS format
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run format \
|
||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out
|
||||
yarn run format && mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
|
||||
|
||||
FROM scratch AS format-update
|
||||
COPY --from=format /out /
|
||||
|
||||
FROM deps AS lint
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run lint
|
||||
|
||||
FROM docker:${DOCKER_VERSION} as docker
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
|
||||
|
||||
FROM deps AS test
|
||||
ENV RUNNER_TEMP=/tmp/github_runner
|
||||
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
--mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
|
||||
--mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
|
||||
yarn run test --coverageDirectory=/tmp/coverage
|
||||
yarn run test --coverage --coverage.reportsDirectory=/tmp/coverage
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage /
|
||||
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
export const id = 606;
|
||||
export const ids = [606];
|
||||
export const modules = {
|
||||
|
||||
/***/ 606:
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ "default": () => (/* binding */ pMap)
|
||||
/* harmony export */ });
|
||||
/* unused harmony exports pMapIterable, pMapSkip */
|
||||
async function pMap(
|
||||
iterable,
|
||||
mapper,
|
||||
{
|
||||
concurrency = Number.POSITIVE_INFINITY,
|
||||
stopOnError = true,
|
||||
signal,
|
||||
} = {},
|
||||
) {
|
||||
return new Promise((resolve_, reject_) => {
|
||||
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
|
||||
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
|
||||
}
|
||||
|
||||
if (typeof mapper !== 'function') {
|
||||
throw new TypeError('Mapper function is required');
|
||||
}
|
||||
|
||||
if (!((Number.isSafeInteger(concurrency) && concurrency >= 1) || concurrency === Number.POSITIVE_INFINITY)) {
|
||||
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
|
||||
}
|
||||
|
||||
const result = [];
|
||||
const errors = [];
|
||||
const skippedIndexesMap = new Map();
|
||||
let isRejected = false;
|
||||
let isResolved = false;
|
||||
let isIterableDone = false;
|
||||
let resolvingCount = 0;
|
||||
let currentIndex = 0;
|
||||
const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
|
||||
|
||||
const signalListener = () => {
|
||||
reject(signal.reason);
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
signal?.removeEventListener('abort', signalListener);
|
||||
};
|
||||
|
||||
const resolve = value => {
|
||||
resolve_(value);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
const reject = reason => {
|
||||
isRejected = true;
|
||||
isResolved = true;
|
||||
reject_(reason);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
if (signal) {
|
||||
if (signal.aborted) {
|
||||
reject(signal.reason);
|
||||
}
|
||||
|
||||
signal.addEventListener('abort', signalListener, {once: true});
|
||||
}
|
||||
|
||||
const next = async () => {
|
||||
if (isResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextItem = await iterator.next();
|
||||
|
||||
const index = currentIndex;
|
||||
currentIndex++;
|
||||
|
||||
// Note: `iterator.next()` can be called many times in parallel.
|
||||
// This can cause multiple calls to this `next()` function to
|
||||
// receive a `nextItem` with `done === true`.
|
||||
// The shutdown logic that rejects/resolves must be protected
|
||||
// so it runs only one time as the `skippedIndex` logic is
|
||||
// non-idempotent.
|
||||
if (nextItem.done) {
|
||||
isIterableDone = true;
|
||||
|
||||
if (resolvingCount === 0 && !isResolved) {
|
||||
if (!stopOnError && errors.length > 0) {
|
||||
reject(new AggregateError(errors)); // eslint-disable-line unicorn/error-message
|
||||
return;
|
||||
}
|
||||
|
||||
isResolved = true;
|
||||
|
||||
if (skippedIndexesMap.size === 0) {
|
||||
resolve(result);
|
||||
return;
|
||||
}
|
||||
|
||||
const pureResult = [];
|
||||
|
||||
// Support multiple `pMapSkip`'s.
|
||||
for (const [index, value] of result.entries()) {
|
||||
if (skippedIndexesMap.get(index) === pMapSkip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pureResult.push(value);
|
||||
}
|
||||
|
||||
resolve(pureResult);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
resolvingCount++;
|
||||
|
||||
// Intentionally detached
|
||||
(async () => {
|
||||
try {
|
||||
const element = await nextItem.value;
|
||||
|
||||
if (isResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = await mapper(element, index);
|
||||
|
||||
// Use Map to stage the index of the element.
|
||||
if (value === pMapSkip) {
|
||||
skippedIndexesMap.set(index, value);
|
||||
}
|
||||
|
||||
result[index] = value;
|
||||
|
||||
resolvingCount--;
|
||||
await next();
|
||||
} catch (error) {
|
||||
if (stopOnError) {
|
||||
reject(error);
|
||||
} else {
|
||||
errors.push(error);
|
||||
resolvingCount--;
|
||||
|
||||
// In that case we can't really continue regardless of `stopOnError` state
|
||||
// since an iterable is likely to continue throwing after it throws once.
|
||||
// If we continue calling `next()` indefinitely we will likely end up
|
||||
// in an infinite loop of failed iteration.
|
||||
try {
|
||||
await next();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
// Create the concurrent runners in a detached (non-awaited)
|
||||
// promise. We need this so we can await the `next()` calls
|
||||
// to stop creating runners before hitting the concurrency limit
|
||||
// if the iterable has already been marked as done.
|
||||
// NOTE: We *must* do this for async iterators otherwise we'll spin up
|
||||
// infinite `next()` calls by default and never start the event loop.
|
||||
(async () => {
|
||||
for (let index = 0; index < concurrency; index++) {
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await next();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (isIterableDone || isRejected) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
function pMapIterable(
|
||||
iterable,
|
||||
mapper,
|
||||
{
|
||||
concurrency = Number.POSITIVE_INFINITY,
|
||||
backpressure = concurrency,
|
||||
} = {},
|
||||
) {
|
||||
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
|
||||
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
|
||||
}
|
||||
|
||||
if (typeof mapper !== 'function') {
|
||||
throw new TypeError('Mapper function is required');
|
||||
}
|
||||
|
||||
if (!((Number.isSafeInteger(concurrency) && concurrency >= 1) || concurrency === Number.POSITIVE_INFINITY)) {
|
||||
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
|
||||
}
|
||||
|
||||
if (!((Number.isSafeInteger(backpressure) && backpressure >= concurrency) || backpressure === Number.POSITIVE_INFINITY)) {
|
||||
throw new TypeError(`Expected \`backpressure\` to be an integer from \`concurrency\` (${concurrency}) and up or \`Infinity\`, got \`${backpressure}\` (${typeof backpressure})`);
|
||||
}
|
||||
|
||||
return {
|
||||
async * [Symbol.asyncIterator]() {
|
||||
const iterator = iterable[Symbol.asyncIterator] === undefined ? iterable[Symbol.iterator]() : iterable[Symbol.asyncIterator]();
|
||||
|
||||
const promises = [];
|
||||
let pendingPromisesCount = 0;
|
||||
let isDone = false;
|
||||
let index = 0;
|
||||
|
||||
function trySpawn() {
|
||||
if (isDone || !(pendingPromisesCount < concurrency && promises.length < backpressure)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pendingPromisesCount++;
|
||||
|
||||
const promise = (async () => {
|
||||
const {done, value} = await iterator.next();
|
||||
|
||||
if (done) {
|
||||
pendingPromisesCount--;
|
||||
return {done: true};
|
||||
}
|
||||
|
||||
// Spawn if still below concurrency and backpressure limit
|
||||
trySpawn();
|
||||
|
||||
try {
|
||||
const returnValue = await mapper(await value, index++);
|
||||
|
||||
pendingPromisesCount--;
|
||||
|
||||
if (returnValue === pMapSkip) {
|
||||
const index = promises.indexOf(promise);
|
||||
|
||||
if (index > 0) {
|
||||
promises.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn if still below backpressure limit and just dropped below concurrency limit
|
||||
trySpawn();
|
||||
|
||||
return {done: false, value: returnValue};
|
||||
} catch (error) {
|
||||
pendingPromisesCount--;
|
||||
isDone = true;
|
||||
return {error};
|
||||
}
|
||||
})();
|
||||
|
||||
promises.push(promise);
|
||||
}
|
||||
|
||||
trySpawn();
|
||||
|
||||
while (promises.length > 0) {
|
||||
const {error, done, value} = await promises[0]; // eslint-disable-line no-await-in-loop
|
||||
|
||||
promises.shift();
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn if just dropped below backpressure limit and below the concurrency limit
|
||||
trySpawn();
|
||||
|
||||
if (value === pMapSkip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield value;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const pMapSkip = Symbol('skip');
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
|
||||
//# sourceMappingURL=606.index.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+115
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+3
-458
@@ -1,466 +1,11 @@
|
||||
@actions/core
|
||||
p-map
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
MIT License
|
||||
|
||||
Copyright 2019 GitHub
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@actions/exec
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@actions/http-client
|
||||
MIT
|
||||
Actions Http Client for Node.js
|
||||
|
||||
Copyright (c) GitHub, Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
@actions/io
|
||||
MIT
|
||||
|
||||
balanced-match
|
||||
MIT
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
brace-expansion
|
||||
MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
concat-map
|
||||
MIT
|
||||
This software is released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
csv-parse
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2010 Adaltas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
fs.realpath
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
----
|
||||
|
||||
This library bundles a version of the `fs.realpath` and `fs.realpathSync`
|
||||
methods from Node.js v0.10 under the terms of the Node.js MIT license.
|
||||
|
||||
Node's license follows, also included at the header of `old.js` which contains
|
||||
the licensed code:
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
glob
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
## Glob Logo
|
||||
|
||||
Glob's logo created by Tanya Brassie <http://tanyabrassie.com/>, licensed
|
||||
under a Creative Commons Attribution-ShareAlike 4.0 International License
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
|
||||
inflight
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
inherits
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
|
||||
lru-cache
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
minimatch
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
once
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
path-is-absolute
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
rimraf
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
semver
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
tmp
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 KARASZI István
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
tunnel
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012 Koichi Kobayashi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
wrappy
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
yallist
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+15
-2
@@ -1,9 +1,15 @@
|
||||
target "_common" {
|
||||
args = {
|
||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
|
||||
}
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["build"]
|
||||
}
|
||||
|
||||
group "pre-checkin" {
|
||||
targets = ["vendor-update", "format", "build"]
|
||||
targets = ["vendor", "format", "build"]
|
||||
}
|
||||
|
||||
group "validate" {
|
||||
@@ -11,42 +17,49 @@ group "validate" {
|
||||
}
|
||||
|
||||
target "build" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "build-validate" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "format" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "format-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "lint" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "lint"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "vendor-update" {
|
||||
target "vendor" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "vendor-validate" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "test" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "test-coverage"
|
||||
output = ["./coverage"]
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import {defineConfig} from 'eslint/config';
|
||||
import js from '@eslint/js';
|
||||
import tseslint from '@typescript-eslint/eslint-plugin';
|
||||
import vitest from '@vitest/eslint-plugin';
|
||||
import globals from 'globals';
|
||||
import eslintConfigPrettier from 'eslint-config-prettier/flat';
|
||||
import eslintPluginPrettier from 'eslint-plugin-prettier';
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
ignores: ['.yarn/**/*', 'coverage/**/*', 'dist/**/*']
|
||||
},
|
||||
js.configs.recommended,
|
||||
...tseslint.configs['flat/recommended'],
|
||||
eslintConfigPrettier,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['__tests__/**'],
|
||||
...vitest.configs.recommended,
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...vitest.environments.env.globals
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...vitest.configs.recommended.rules,
|
||||
'vitest/no-conditional-expect': 'error',
|
||||
'vitest/no-disabled-tests': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
prettier: eslintPluginPrettier
|
||||
},
|
||||
rules: {
|
||||
'prettier/prettier': 'error',
|
||||
'@typescript-eslint/no-require-imports': [
|
||||
'error',
|
||||
{
|
||||
allowAsImport: true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]);
|
||||
@@ -1,13 +0,0 @@
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
setupFiles: ['dotenv/config'],
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
|
||||
},
|
||||
verbose: true
|
||||
};
|
||||
+25
-35
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "docker-buildx-bake",
|
||||
"description": "GitHub Action to use Docker Buildx Bake as a high-level build command",
|
||||
"main": "lib/main.js",
|
||||
"type": "module",
|
||||
"main": "src/main.ts",
|
||||
"scripts": {
|
||||
"build": "ncc build src/main.ts --source-map --minify --license licenses.txt",
|
||||
"lint": "eslint src/**/*.ts __tests__/**/*.ts",
|
||||
"format": "eslint --fix src/**/*.ts __tests__/**/*.ts",
|
||||
"test": "jest --coverage",
|
||||
"all": "yarn run build && yarn run format && yarn test"
|
||||
"build": "ncc build --source-map --minify --license licenses.txt",
|
||||
"lint": "eslint --max-warnings=0 .",
|
||||
"format": "eslint --fix .",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -19,38 +19,28 @@
|
||||
"buildx",
|
||||
"bake"
|
||||
],
|
||||
"author": "Docker",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "CrazyMax",
|
||||
"url": "https://crazymax.dev"
|
||||
}
|
||||
],
|
||||
"author": "Docker Inc.",
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"csv-parse": "^5.0.4",
|
||||
"semver": "^7.3.7",
|
||||
"tmp": "^0.2.1"
|
||||
"@actions/core": "^3.0.0",
|
||||
"@docker/actions-toolkit": "^0.79.0",
|
||||
"handlebars": "^4.7.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/csv-parse": "^1.2.2",
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/semver": "^7.3.9",
|
||||
"@types/tmp": "^0.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
||||
"@typescript-eslint/parser": "^5.14.0",
|
||||
"@vercel/ncc": "^0.33.3",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-jest": "^26.1.1",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "^27.2.5",
|
||||
"prettier": "^2.3.1",
|
||||
"ts-jest": "^27.1.2",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "^4.4.4"
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@types/node": "^24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
||||
"@typescript-eslint/parser": "^8.56.1",
|
||||
"@vercel/ncc": "^0.38.4",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"@vitest/eslint-plugin": "^1.6.9",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
"globals": "^17.3.0",
|
||||
"prettier": "^3.8.1",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.0.18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
import * as context from './context';
|
||||
|
||||
export async function getMetadataFile(): Promise<string> {
|
||||
return path.join(context.tmpDir(), 'metadata-file').split(path.sep).join(path.posix.sep);
|
||||
}
|
||||
|
||||
export async function getMetadata(): Promise<string | undefined> {
|
||||
const metadataFile = await getMetadataFile();
|
||||
if (!fs.existsSync(metadataFile)) {
|
||||
return undefined;
|
||||
}
|
||||
const content = fs.readFileSync(metadataFile, {encoding: 'utf-8'}).trim();
|
||||
if (content === 'null') {
|
||||
return undefined;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
export async function isAvailable(standalone?: boolean): Promise<boolean> {
|
||||
const cmd = getCommand([], standalone);
|
||||
return await exec
|
||||
.getExecOutput(cmd.command, cmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
return false;
|
||||
}
|
||||
return res.exitCode == 0;
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.catch(error => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
export async function getVersion(standalone?: boolean): Promise<string> {
|
||||
const cmd = getCommand(['version'], standalone);
|
||||
return await exec
|
||||
.getExecOutput(cmd.command, cmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
return parseVersion(res.stdout.trim());
|
||||
});
|
||||
}
|
||||
|
||||
export function parseVersion(stdout: string): string {
|
||||
const matches = /\sv?([0-9a-f]{7}|[0-9.]+)/.exec(stdout);
|
||||
if (!matches) {
|
||||
throw new Error(`Cannot parse buildx version`);
|
||||
}
|
||||
return matches[1];
|
||||
}
|
||||
|
||||
export function satisfies(version: string, range: string): boolean {
|
||||
return semver.satisfies(version, range) || /^[0-9a-f]{7}$/.exec(version) !== null;
|
||||
}
|
||||
|
||||
export function getCommand(args: Array<string>, standalone?: boolean) {
|
||||
return {
|
||||
command: standalone ? 'buildx' : 'docker',
|
||||
args: standalone ? args : ['buildx', ...args]
|
||||
};
|
||||
}
|
||||
+106
-64
@@ -1,75 +1,127 @@
|
||||
import {parse} from 'csv-parse/sync';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as tmp from 'tmp';
|
||||
import * as buildx from './buildx';
|
||||
import * as core from '@actions/core';
|
||||
import {issueCommand} from '@actions/core/lib/command';
|
||||
import * as handlebars from 'handlebars';
|
||||
|
||||
let _tmpDir: string;
|
||||
import {Bake} from '@docker/actions-toolkit/lib/buildx/bake.js';
|
||||
import {Build} from '@docker/actions-toolkit/lib/buildx/build.js';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context.js';
|
||||
import {GitHub} from '@docker/actions-toolkit/lib/github/github.js';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
|
||||
import {Util} from '@docker/actions-toolkit/lib/util.js';
|
||||
|
||||
import {BakeDefinition} from '@docker/actions-toolkit/lib/types/buildx/bake.js';
|
||||
|
||||
export interface BakeContext {
|
||||
remoteRef?: string;
|
||||
workdir?: string;
|
||||
}
|
||||
|
||||
export interface Inputs {
|
||||
builder: string;
|
||||
allow: string[];
|
||||
call: string;
|
||||
files: string[];
|
||||
targets: string[];
|
||||
noCache: boolean;
|
||||
'no-cache': boolean;
|
||||
pull: boolean;
|
||||
load: boolean;
|
||||
provenance: string;
|
||||
push: boolean;
|
||||
sbom: string;
|
||||
set: string[];
|
||||
}
|
||||
|
||||
export function tmpDir(): string {
|
||||
if (!_tmpDir) {
|
||||
_tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-')).split(path.sep).join(path.posix.sep);
|
||||
}
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
export function tmpNameSync(options?: tmp.TmpNameOptions): string {
|
||||
return tmp.tmpNameSync(options);
|
||||
source: BakeContext;
|
||||
targets: string[];
|
||||
'github-token': string;
|
||||
}
|
||||
|
||||
export async function getInputs(): Promise<Inputs> {
|
||||
return {
|
||||
builder: core.getInput('builder'),
|
||||
files: getInputList('files'),
|
||||
targets: getInputList('targets'),
|
||||
noCache: core.getBooleanInput('no-cache'),
|
||||
allow: Util.getInputList('allow'),
|
||||
call: core.getInput('call'),
|
||||
files: Util.getInputList('files'),
|
||||
'no-cache': core.getBooleanInput('no-cache'),
|
||||
pull: core.getBooleanInput('pull'),
|
||||
load: core.getBooleanInput('load'),
|
||||
provenance: Build.getProvenanceInput('provenance'),
|
||||
push: core.getBooleanInput('push'),
|
||||
set: getInputList('set', true)
|
||||
sbom: core.getInput('sbom'),
|
||||
set: Util.getInputList('set', {ignoreComma: true, quote: false}),
|
||||
source: getBakeContext(core.getInput('source')),
|
||||
targets: Util.getInputList('targets'),
|
||||
'github-token': core.getInput('github-token')
|
||||
};
|
||||
}
|
||||
|
||||
export async function getArgs(inputs: Inputs, buildxVersion: string): Promise<Array<string>> {
|
||||
export async function getArgs(inputs: Inputs, definition: BakeDefinition, toolkit: Toolkit): Promise<Array<string>> {
|
||||
// prettier-ignore
|
||||
return [
|
||||
...await getBakeArgs(inputs, buildxVersion),
|
||||
...await getBakeArgs(inputs, definition, toolkit),
|
||||
...await getCommonArgs(inputs),
|
||||
...inputs.targets
|
||||
];
|
||||
}
|
||||
|
||||
async function getBakeArgs(inputs: Inputs, buildxVersion: string): Promise<Array<string>> {
|
||||
async function getBakeArgs(inputs: Inputs, definition: BakeDefinition, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const args: Array<string> = ['bake'];
|
||||
await asyncForEach(inputs.files, async file => {
|
||||
if (inputs.source.remoteRef) {
|
||||
args.push(inputs.source.remoteRef);
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.17.0')) {
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.18.0')) {
|
||||
// allow filesystem entitlements by default
|
||||
inputs.allow.push('fs=*');
|
||||
}
|
||||
await Util.asyncForEach(inputs.allow, async allow => {
|
||||
args.push('--allow', allow);
|
||||
});
|
||||
}
|
||||
if (inputs.call) {
|
||||
if (!(await toolkit.buildx.versionSatisfies('>=0.16.0'))) {
|
||||
throw new Error(`Buildx >= 0.16.0 is required to use the call flag.`);
|
||||
}
|
||||
args.push('--call', inputs.call);
|
||||
}
|
||||
await Util.asyncForEach(inputs.files, async file => {
|
||||
args.push('--file', file);
|
||||
});
|
||||
await asyncForEach(inputs.set, async set => {
|
||||
await Util.asyncForEach(inputs.set, async set => {
|
||||
args.push('--set', set);
|
||||
});
|
||||
if (buildx.satisfies(buildxVersion, '>=0.6.0')) {
|
||||
args.push('--metadata-file', await buildx.getMetadataFile());
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.6.0')) {
|
||||
args.push('--metadata-file', toolkit.buildxBake.getMetadataFilePath());
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.10.0')) {
|
||||
if (inputs.provenance) {
|
||||
args.push('--provenance', inputs.provenance);
|
||||
} else if (!noDefaultAttestations() && (await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !Bake.hasDockerExporter(definition, inputs.load)) {
|
||||
// check if provenance attestation is already specified in the bake
|
||||
// definition and if not specified and BuildKit version compatible for
|
||||
// attestation, set default provenance. Also needs to make sure user
|
||||
// doesn't want to explicitly load the image to docker.
|
||||
for (const targetName in definition.target) {
|
||||
const target = definition.target[targetName];
|
||||
if (!Array.isArray(target.attest) || !target.attest.some(attest => attest?.type === 'provenance')) {
|
||||
if (GitHub.context.payload.repository?.private ?? false) {
|
||||
// if this is a private repository, we set the default provenance
|
||||
// attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
|
||||
args.push('--set', `${targetName}.attest=type=provenance,${Build.resolveProvenanceAttrs(`mode=min,inline-only=true`)}`);
|
||||
} else {
|
||||
// for a public repository, we set max provenance mode.
|
||||
args.push('--set', `${targetName}.attest=type=provenance,${Build.resolveProvenanceAttrs(`mode=max`)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inputs.sbom) {
|
||||
args.push('--sbom', inputs.sbom);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
async function getCommonArgs(inputs: Inputs): Promise<Array<string>> {
|
||||
const args: Array<string> = [];
|
||||
if (inputs.noCache) {
|
||||
if (inputs['no-cache']) {
|
||||
args.push('--no-cache');
|
||||
}
|
||||
if (inputs.builder) {
|
||||
@@ -87,41 +139,31 @@ async function getCommonArgs(inputs: Inputs): Promise<Array<string>> {
|
||||
return args;
|
||||
}
|
||||
|
||||
export function getInputList(name: string, ignoreComma?: boolean): string[] {
|
||||
const res: Array<string> = [];
|
||||
|
||||
const items = core.getInput(name);
|
||||
if (items == '') {
|
||||
return res;
|
||||
}
|
||||
|
||||
const records = parse(items, {
|
||||
columns: false,
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
function getBakeContext(sourceInput: string): BakeContext {
|
||||
let bakeContext = handlebars.compile(sourceInput)({
|
||||
defaultContext: Context.gitContext()
|
||||
});
|
||||
|
||||
for (const record of records as Array<string[]>) {
|
||||
if (record.length == 1) {
|
||||
res.push(record[0]);
|
||||
continue;
|
||||
} else if (!ignoreComma) {
|
||||
res.push(...record);
|
||||
continue;
|
||||
}
|
||||
res.push(record.join(','));
|
||||
if (!bakeContext) {
|
||||
bakeContext = Context.gitContext();
|
||||
}
|
||||
|
||||
return res.filter(item => item).map(pat => pat.trim());
|
||||
if (Util.isValidRef(bakeContext)) {
|
||||
return {
|
||||
remoteRef: bakeContext
|
||||
};
|
||||
}
|
||||
try {
|
||||
fs.statSync(sourceInput).isDirectory();
|
||||
} catch {
|
||||
throw new Error(`Invalid source: ${sourceInput} does not exist or is not a directory.`);
|
||||
}
|
||||
return {
|
||||
workdir: bakeContext
|
||||
};
|
||||
}
|
||||
|
||||
export const asyncForEach = async (array, callback) => {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
function noDefaultAttestations(): boolean {
|
||||
if (process.env.BUILDX_NO_DEFAULT_ATTESTATIONS) {
|
||||
return Util.parseBool(process.env.BUILDX_NO_DEFAULT_ATTESTATIONS);
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: Temp fix https://github.com/actions/toolkit/issues/777
|
||||
export function setOutput(name: string, value: unknown): void {
|
||||
issueCommand('set-output', {name}, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
export async function isAvailable(): Promise<boolean> {
|
||||
return await exec
|
||||
.getExecOutput('docker', undefined, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
return false;
|
||||
}
|
||||
return res.exitCode == 0;
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.catch(error => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
+306
-57
@@ -1,84 +1,333 @@
|
||||
import * as fs from 'fs';
|
||||
import * as buildx from './buildx';
|
||||
import * as context from './context';
|
||||
import * as docker from './docker';
|
||||
import * as stateHelper from './state-helper';
|
||||
import * as path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as actionsToolkit from '@docker/actions-toolkit';
|
||||
|
||||
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx.js';
|
||||
import {History as BuildxHistory} from '@docker/actions-toolkit/lib/buildx/history.js';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context.js';
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker.js';
|
||||
import {Exec} from '@docker/actions-toolkit/lib/exec.js';
|
||||
import {GitHub} from '@docker/actions-toolkit/lib/github/github.js';
|
||||
import {GitHubArtifact} from '@docker/actions-toolkit/lib/github/artifact.js';
|
||||
import {GitHubSummary} from '@docker/actions-toolkit/lib/github/summary.js';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit.js';
|
||||
import {Util} from '@docker/actions-toolkit/lib/util.js';
|
||||
|
||||
import {BakeDefinition} from '@docker/actions-toolkit/lib/types/buildx/bake.js';
|
||||
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder.js';
|
||||
import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker.js';
|
||||
import {UploadResponse as UploadArtifactResponse} from '@docker/actions-toolkit/lib/types/github/artifact.js';
|
||||
|
||||
import * as context from './context.js';
|
||||
import * as stateHelper from './state-helper.js';
|
||||
|
||||
actionsToolkit.run(
|
||||
// main
|
||||
async () => {
|
||||
const startedTime = new Date();
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
const inputs: context.Inputs = await context.getInputs();
|
||||
stateHelper.setSummaryInputs(inputs);
|
||||
core.debug(`inputs: ${JSON.stringify(inputs)}`);
|
||||
|
||||
// standalone if docker cli not available
|
||||
const standalone = !(await docker.isAvailable());
|
||||
const toolkit = new Toolkit();
|
||||
const gitAuthToken = process.env.BUILDX_BAKE_GIT_AUTH_TOKEN ?? inputs['github-token'];
|
||||
|
||||
core.startGroup(`Docker info`);
|
||||
if (standalone) {
|
||||
core.info(`Docker info skipped in standalone mode`);
|
||||
} else {
|
||||
await exec.exec('docker', ['version'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
await exec.exec('docker', ['info'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
}
|
||||
core.endGroup();
|
||||
await core.group(`GitHub Actions runtime token ACs`, async () => {
|
||||
try {
|
||||
await GitHub.printActionsRuntimeTokenACs();
|
||||
} catch (e) {
|
||||
core.warning(e.message);
|
||||
}
|
||||
});
|
||||
|
||||
if (!(await buildx.isAvailable(standalone))) {
|
||||
await core.group(`Docker info`, async () => {
|
||||
try {
|
||||
await Docker.printVersion();
|
||||
await Docker.printInfo();
|
||||
} catch (e) {
|
||||
core.info(e.message);
|
||||
}
|
||||
});
|
||||
|
||||
await core.group(`Proxy configuration`, async () => {
|
||||
let dockerConfig: ConfigFile | undefined;
|
||||
let dockerConfigMalformed = false;
|
||||
try {
|
||||
dockerConfig = await Docker.configFile();
|
||||
} catch (e) {
|
||||
dockerConfigMalformed = true;
|
||||
core.warning(`Unable to parse config file ${path.join(Docker.configDir, 'config.json')}: ${e}`);
|
||||
}
|
||||
if (dockerConfig && dockerConfig.proxies) {
|
||||
for (const host in dockerConfig.proxies) {
|
||||
let prefix = '';
|
||||
if (Object.keys(dockerConfig.proxies).length > 1) {
|
||||
prefix = ' ';
|
||||
core.info(host);
|
||||
}
|
||||
for (const key in dockerConfig.proxies[host]) {
|
||||
core.info(`${prefix}${key}: ${dockerConfig.proxies[host][key]}`);
|
||||
}
|
||||
}
|
||||
} else if (!dockerConfigMalformed) {
|
||||
core.info('No proxy configuration found');
|
||||
}
|
||||
});
|
||||
|
||||
if (!(await toolkit.buildx.isAvailable())) {
|
||||
core.setFailed(`Docker buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
||||
return;
|
||||
}
|
||||
stateHelper.setTmpDir(context.tmpDir());
|
||||
|
||||
const buildxVersion = await buildx.getVersion(standalone);
|
||||
stateHelper.setTmpDir(Context.tmpDir());
|
||||
|
||||
await core.group(`Buildx version`, async () => {
|
||||
const versionCmd = buildx.getCommand(['version'], standalone);
|
||||
await exec.exec(versionCmd.command, versionCmd.args, {
|
||||
failOnStdErr: false
|
||||
await toolkit.buildx.printVersion();
|
||||
});
|
||||
|
||||
let builder: BuilderInfo;
|
||||
await core.group(`Builder info`, async () => {
|
||||
builder = await toolkit.builder.inspect(inputs.builder);
|
||||
stateHelper.setBuilderDriver(builder.driver ?? '');
|
||||
stateHelper.setBuilderEndpoint(builder.nodes?.[0]?.endpoint ?? '');
|
||||
core.info(JSON.stringify(builder, null, 2));
|
||||
});
|
||||
|
||||
let definition: BakeDefinition | undefined;
|
||||
await core.group(`Parsing raw definition`, async () => {
|
||||
definition = await toolkit.buildxBake.getDefinition(
|
||||
{
|
||||
allow: inputs.allow,
|
||||
files: inputs.files,
|
||||
load: inputs.load,
|
||||
noCache: inputs['no-cache'],
|
||||
overrides: inputs.set,
|
||||
provenance: inputs.provenance,
|
||||
push: inputs.push,
|
||||
sbom: inputs.sbom,
|
||||
source: inputs.source.remoteRef,
|
||||
targets: inputs.targets,
|
||||
githubToken: gitAuthToken
|
||||
},
|
||||
{
|
||||
cwd: inputs.source.workdir
|
||||
}
|
||||
);
|
||||
});
|
||||
if (!definition) {
|
||||
throw new Error('Bake definition not set');
|
||||
}
|
||||
stateHelper.setBakeDefinition(definition);
|
||||
|
||||
const args: string[] = await context.getArgs(inputs, definition, toolkit);
|
||||
const buildCmd = await toolkit.buildx.getCommand(args);
|
||||
const buildEnv = Object.assign({}, process.env, {
|
||||
BUILDX_BAKE_GIT_AUTH_TOKEN: gitAuthToken,
|
||||
BUILDX_METADATA_WARNINGS: 'true'
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
await core.group(`Bake definition`, async () => {
|
||||
await Exec.getExecOutput(buildCmd.command, [...buildCmd.args, '--print'], {
|
||||
cwd: inputs.source.workdir,
|
||||
env: buildEnv,
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw Error(res.stderr);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const args: string[] = await context.getArgs(inputs, buildxVersion);
|
||||
const buildCmd = buildx.getCommand(args, standalone);
|
||||
|
||||
core.startGroup(`Bake definition`);
|
||||
await exec.exec(buildCmd.command, [...buildCmd.args, '--print']);
|
||||
core.endGroup();
|
||||
|
||||
await exec
|
||||
.getExecOutput(buildCmd.command, buildCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(`buildx bake failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
let err: Error | undefined;
|
||||
await Exec.getExecOutput(buildCmd.command, buildCmd.args, {
|
||||
cwd: inputs.source.workdir,
|
||||
env: buildEnv,
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.exitCode != 0) {
|
||||
if (inputs.call && inputs.call === 'check' && res.stdout.length > 0) {
|
||||
// checks warnings are printed to stdout: https://github.com/docker/buildx/pull/2647
|
||||
// with bake we can have multiple targets being checked so we need to
|
||||
// count the total number of warnings
|
||||
const totalWarnings = [...res.stdout.matchAll(/^Check complete, (\d+) warnings? (?:has|have) been found!/gm)].reduce((sum, m) => sum + parseInt(m[1], 10), 0);
|
||||
if (totalWarnings > 0) {
|
||||
// https://github.com/docker/buildx/blob/1e50e8ddabe108f009b9925e13a321d7c8f99f26/commands/build.go#L797-L803
|
||||
if (totalWarnings === 1) {
|
||||
err = Error(`Check complete, ${totalWarnings} warning has been found!`);
|
||||
} else {
|
||||
err = Error(`Check complete, ${totalWarnings} warnings have been found!`);
|
||||
}
|
||||
} else {
|
||||
// if there are no warnings found, return the first line of stdout
|
||||
err = Error(res.stdout.split('\n')[0]?.trim());
|
||||
}
|
||||
} else if (res.stderr.length > 0) {
|
||||
err = Error(`buildx bake failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const metadata = await buildx.getMetadata();
|
||||
const metadata = toolkit.buildxBake.resolveMetadata();
|
||||
if (metadata) {
|
||||
await core.group(`Metadata output`, async () => {
|
||||
core.info(metadata);
|
||||
context.setOutput('metadata', metadata);
|
||||
await core.group(`Metadata`, async () => {
|
||||
const metadatadt = JSON.stringify(metadata, null, 2);
|
||||
core.info(metadatadt);
|
||||
core.setOutput('metadata', metadatadt);
|
||||
});
|
||||
}
|
||||
|
||||
let refs: Array<string> = [];
|
||||
await core.group(`Build references`, async () => {
|
||||
refs = await buildRefs(toolkit, startedTime, inputs.builder);
|
||||
if (refs.length > 0) {
|
||||
for (const ref of refs) {
|
||||
core.info(ref);
|
||||
}
|
||||
stateHelper.setBuildRefs(refs);
|
||||
} else {
|
||||
core.info('No build references found');
|
||||
}
|
||||
});
|
||||
|
||||
if (buildChecksAnnotationsEnabled()) {
|
||||
const warnings = toolkit.buildxBake.resolveWarnings(metadata);
|
||||
if (refs.length > 0 && warnings && warnings.length > 0) {
|
||||
const annotations = await Buildx.convertWarningsToGitHubAnnotations(warnings, refs);
|
||||
core.debug(`annotations: ${JSON.stringify(annotations, null, 2)}`);
|
||||
if (annotations && annotations.length > 0) {
|
||||
await core.group(`Generating GitHub annotations (${annotations.length} build checks found)`, async () => {
|
||||
for (const annotation of annotations) {
|
||||
core.warning(annotation.message, annotation);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await core.group(`Check build summary support`, async () => {
|
||||
if (!buildSummaryEnabled()) {
|
||||
core.info('Build summary disabled');
|
||||
} else if (inputs.call && inputs.call !== 'build') {
|
||||
core.info(`Build summary skipped for ${inputs.call} subrequest`);
|
||||
} else if (GitHub.isGHES) {
|
||||
core.info('Build summary is not yet supported on GHES');
|
||||
} else if (!(await toolkit.buildx.versionSatisfies('>=0.23.0'))) {
|
||||
core.info('Build summary requires Buildx >= 0.23.0');
|
||||
} else if (refs.length == 0) {
|
||||
core.info('Build summary requires at least one build reference');
|
||||
} else {
|
||||
core.info('Build summary supported!');
|
||||
stateHelper.setSummarySupported();
|
||||
}
|
||||
});
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
// post
|
||||
async () => {
|
||||
if (stateHelper.isSummarySupported) {
|
||||
await core.group(`Generating build summary`, async () => {
|
||||
try {
|
||||
const recordUploadEnabled = buildRecordUploadEnabled();
|
||||
let recordRetentionDays: number | undefined;
|
||||
if (recordUploadEnabled) {
|
||||
recordRetentionDays = buildRecordRetentionDays();
|
||||
}
|
||||
|
||||
const buildxHistory = new BuildxHistory();
|
||||
const exportRes = await buildxHistory.export({
|
||||
refs: stateHelper.buildRefs
|
||||
});
|
||||
core.info(`Build records written to ${exportRes.dockerbuildFilename} (${Util.formatFileSize(exportRes.dockerbuildSize)})`);
|
||||
|
||||
let uploadRes: UploadArtifactResponse | undefined;
|
||||
if (recordUploadEnabled) {
|
||||
uploadRes = await GitHubArtifact.upload({
|
||||
filename: exportRes.dockerbuildFilename,
|
||||
retentionDays: recordRetentionDays
|
||||
});
|
||||
}
|
||||
|
||||
await GitHubSummary.writeBuildSummary({
|
||||
exportRes: exportRes,
|
||||
uploadRes: uploadRes,
|
||||
inputs: stateHelper.summaryInputs,
|
||||
bakeDefinition: stateHelper.bakeDefinition,
|
||||
driver: stateHelper.builderDriver,
|
||||
endpoint: stateHelper.builderEndpoint
|
||||
});
|
||||
} catch (e) {
|
||||
core.warning(e.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (stateHelper.tmpDir.length > 0) {
|
||||
await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => {
|
||||
fs.rmSync(stateHelper.tmpDir, {recursive: true});
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
);
|
||||
|
||||
async function buildRefs(toolkit: Toolkit, since: Date, builder?: string): Promise<Array<string>> {
|
||||
// get refs from metadata file
|
||||
const metaRefs = toolkit.buildxBake.resolveRefs();
|
||||
if (metaRefs) {
|
||||
return metaRefs;
|
||||
}
|
||||
// otherwise, look for the very first build ref since the build has started
|
||||
if (!builder) {
|
||||
const currentBuilder = await toolkit.builder.inspect();
|
||||
builder = currentBuilder.name;
|
||||
}
|
||||
const res = Buildx.refs({
|
||||
dir: Buildx.refsDir,
|
||||
builderName: builder,
|
||||
since: since
|
||||
});
|
||||
const refs: Array<string> = [];
|
||||
for (const ref in res) {
|
||||
if (Object.prototype.hasOwnProperty.call(res, ref)) {
|
||||
refs.push(ref);
|
||||
}
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
async function cleanup(): Promise<void> {
|
||||
if (stateHelper.tmpDir.length > 0) {
|
||||
core.startGroup(`Removing temp folder ${stateHelper.tmpDir}`);
|
||||
fs.rmdirSync(stateHelper.tmpDir, {recursive: true});
|
||||
core.endGroup();
|
||||
function buildChecksAnnotationsEnabled(): boolean {
|
||||
if (process.env.DOCKER_BUILD_CHECKS_ANNOTATIONS) {
|
||||
return Util.parseBool(process.env.DOCKER_BUILD_CHECKS_ANNOTATIONS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!stateHelper.IsPost) {
|
||||
run();
|
||||
} else {
|
||||
cleanup();
|
||||
function buildSummaryEnabled(): boolean {
|
||||
if (process.env.DOCKER_BUILD_SUMMARY) {
|
||||
return Util.parseBool(process.env.DOCKER_BUILD_SUMMARY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildRecordUploadEnabled(): boolean {
|
||||
if (process.env.DOCKER_BUILD_RECORD_UPLOAD) {
|
||||
return Util.parseBool(process.env.DOCKER_BUILD_RECORD_UPLOAD);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildRecordRetentionDays(): number | undefined {
|
||||
const val = process.env.DOCKER_BUILD_RECORD_RETENTION_DAYS;
|
||||
if (val) {
|
||||
const res = parseInt(val);
|
||||
if (isNaN(res)) {
|
||||
throw Error(`Invalid build record retention days: ${val}`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
+52
-3
@@ -1,12 +1,61 @@
|
||||
import * as core from '@actions/core';
|
||||
|
||||
export const IsPost = !!process.env['STATE_isPost'];
|
||||
import {BakeDefinition} from '@docker/actions-toolkit/lib/types/buildx/bake.js';
|
||||
|
||||
import {Inputs} from './context.js';
|
||||
|
||||
export const tmpDir = process.env['STATE_tmpDir'] || '';
|
||||
|
||||
export const builderDriver = process.env['STATE_builderDriver'] || '';
|
||||
export const builderEndpoint = process.env['STATE_builderEndpoint'] || '';
|
||||
export const summaryInputs = process.env['STATE_summaryInputs'] ? JSON.parse(process.env['STATE_summaryInputs']) : undefined;
|
||||
export const bakeDefinition = process.env['STATE_bakeDefinition'] ? <BakeDefinition>JSON.parse(process.env['STATE_bakeDefinition']) : undefined;
|
||||
|
||||
export const buildRefs = process.env['STATE_buildRefs'] ? process.env['STATE_buildRefs'].split(',') : [];
|
||||
export const isSummarySupported = !!process.env['STATE_isSummarySupported'];
|
||||
|
||||
export function setTmpDir(tmpDir: string) {
|
||||
core.saveState('tmpDir', tmpDir);
|
||||
}
|
||||
|
||||
if (!IsPost) {
|
||||
core.saveState('isPost', 'true');
|
||||
export function setBuilderDriver(builderDriver: string) {
|
||||
core.saveState('builderDriver', builderDriver);
|
||||
}
|
||||
|
||||
export function setBuilderEndpoint(builderEndpoint: string) {
|
||||
core.saveState('builderEndpoint', builderEndpoint);
|
||||
}
|
||||
|
||||
export function setBakeDefinition(bakeDefinition: BakeDefinition) {
|
||||
core.saveState('bakeDefinition', JSON.stringify(bakeDefinition));
|
||||
}
|
||||
|
||||
export function setBuildRefs(buildRefs: Array<string>) {
|
||||
core.saveState('buildRefs', buildRefs.join(','));
|
||||
}
|
||||
|
||||
export function setSummarySupported() {
|
||||
core.saveState('isSummarySupported', 'true');
|
||||
}
|
||||
|
||||
export function setSummaryInputs(inputs: Inputs) {
|
||||
const res = {};
|
||||
if (inputs.source.remoteRef || inputs.source.workdir) {
|
||||
res['source'] = inputs.source.remoteRef || inputs.source.workdir;
|
||||
}
|
||||
for (const key of Object.keys(inputs)) {
|
||||
if (key === 'source' || key === 'github-token') {
|
||||
continue;
|
||||
}
|
||||
const value: string | string[] | boolean = inputs[key];
|
||||
if (typeof value === 'boolean' && !value) {
|
||||
continue;
|
||||
} else if (Array.isArray(value) && value.length === 0) {
|
||||
continue;
|
||||
} else if (!value) {
|
||||
continue;
|
||||
}
|
||||
res[key] = value;
|
||||
}
|
||||
core.saveState('summaryInputs', JSON.stringify(res));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
## About
|
||||
|
||||
This subaction generates a multi-dimension matrix that can be used in a [GitHub matrix](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix)
|
||||
through the [`include` property](https://docs.github.com/en/actions/how-tos/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow#expanding-or-adding-matrix-configurations)
|
||||
so you can distribute your builds across multiple runners.
|
||||
|
||||

|
||||
|
||||
___
|
||||
|
||||
* [Usage](#usage)
|
||||
* [Customizing](#customizing)
|
||||
* [inputs](#inputs)
|
||||
* [outputs](#outputs)
|
||||
|
||||
## Usage
|
||||
|
||||
### List targets
|
||||
|
||||
```hcl
|
||||
# docker-bake.hcl
|
||||
group "validate" {
|
||||
targets = ["lint", "doctoc"]
|
||||
}
|
||||
|
||||
target "lint" {
|
||||
target = "lint"
|
||||
}
|
||||
|
||||
target "doctoc" {
|
||||
target = "doctoc"
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Generate matrix
|
||||
id: generate
|
||||
uses: docker/bake-action/subaction/matrix@v6
|
||||
with:
|
||||
target: validate
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
steps:
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
```
|
||||
|
||||
### Platforms split
|
||||
|
||||
```hcl
|
||||
# docker-bake.hcl
|
||||
target "lint" {
|
||||
dockerfile = "./hack/dockerfiles/lint.Dockerfile"
|
||||
output = ["type=cacheonly"]
|
||||
platforms = [
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"linux/amd64",
|
||||
"linux/arm64",
|
||||
"linux/s390x",
|
||||
"linux/ppc64le",
|
||||
"linux/riscv64",
|
||||
"windows/amd64",
|
||||
"windows/arm64"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Generate matrix
|
||||
id: generate
|
||||
uses: docker/bake-action/subaction/matrix@v6
|
||||
with:
|
||||
target: lint
|
||||
fields: platforms
|
||||
|
||||
lint:
|
||||
runs-on: ${{ startsWith(matrix.platforms, 'linux/arm') && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
steps:
|
||||
-
|
||||
name: Lint
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
set: |
|
||||
*.platform=${{ matrix.platforms }}
|
||||
```
|
||||
|
||||
## Customizing
|
||||
|
||||
### inputs
|
||||
|
||||
| Name | Type | Description |
|
||||
|-----------|----------|------------------------------------------------------------------------------------------------|
|
||||
| `workdir` | String | Working directory to use (defaults to `.`) |
|
||||
| `files` | List/CSV | List of [bake definition files](https://docs.docker.com/build/customize/bake/file-definition/) |
|
||||
| `target` | String | The target to use within the bake file |
|
||||
| `fields` | String | List of extra fields to include in the matrix |
|
||||
|
||||
### outputs
|
||||
|
||||
| Name | Type | Description |
|
||||
|----------|------|----------------------|
|
||||
| `matrix` | JSON | Matrix configuration |
|
||||
@@ -0,0 +1,101 @@
|
||||
# https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions
|
||||
name: 'Matrix'
|
||||
description: 'Generate a matrix from a Bake definition to help distributing builds in your workflow'
|
||||
|
||||
inputs:
|
||||
workdir:
|
||||
description: Working directory
|
||||
default: '.'
|
||||
required: false
|
||||
files:
|
||||
description: List of Bake files
|
||||
required: false
|
||||
target:
|
||||
description: Bake target
|
||||
required: false
|
||||
fields:
|
||||
description: List of extra fields to include in the matrix
|
||||
required: false
|
||||
|
||||
outputs:
|
||||
matrix:
|
||||
description: Matrix configuration
|
||||
value: ${{ steps.generate.outputs.includes }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
-
|
||||
name: Generate
|
||||
id: generate
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
INPUT_WORKDIR: ${{ inputs.workdir }}
|
||||
INPUT_FILES: ${{ inputs.files }}
|
||||
INPUT_TARGET: ${{ inputs.target }}
|
||||
INPUT_FIELDS: ${{ inputs.fields }}
|
||||
with:
|
||||
script: |
|
||||
function getInputList(name) {
|
||||
return core.getInput(name) ? core.getInput(name).split(/[\r?\n,]+/).filter(x => x !== '') : [];
|
||||
}
|
||||
|
||||
const workdir = core.getInput('workdir');
|
||||
const files = getInputList('files');
|
||||
const target = core.getInput('target');
|
||||
const fields = getInputList('fields');
|
||||
|
||||
let def = {};
|
||||
await core.group(`Parsing definition`, async () => {
|
||||
let args = ['buildx', 'bake'];
|
||||
for (const file of files) {
|
||||
args.push('--file', file);
|
||||
}
|
||||
if (target) {
|
||||
args.push(target);
|
||||
}
|
||||
args.push('--print');
|
||||
const res = await exec.getExecOutput('docker', args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true,
|
||||
cwd: workdir
|
||||
});
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr);
|
||||
}
|
||||
def = JSON.parse(res.stdout.trim());
|
||||
core.info(JSON.stringify(def, null, 2));
|
||||
});
|
||||
|
||||
await core.group(`Generating matrix`, async () => {
|
||||
const result = [];
|
||||
for (const targetName of Object.keys(def.target)) {
|
||||
const target = def.target[targetName];
|
||||
const entry = { target: targetName };
|
||||
if (fields.length === 0) {
|
||||
result.push({ ...entry });
|
||||
continue;
|
||||
}
|
||||
let fieldFound = false;
|
||||
Object.keys(target).forEach(field => {
|
||||
if (fields.includes(field)) {
|
||||
fieldFound = true;
|
||||
const value = target[field];
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((v) => {
|
||||
entry[field] = v;
|
||||
result.push({ ...entry });
|
||||
});
|
||||
} else {
|
||||
entry[field] = value;
|
||||
result.push({ ...entry });
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!fieldFound) {
|
||||
result.push({ ...entry });
|
||||
}
|
||||
}
|
||||
core.info(JSON.stringify(result, null, 2));
|
||||
core.setOutput('includes', JSON.stringify(result));
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM busybox AS t1
|
||||
RUN echo "Hello t1"
|
||||
|
||||
FROM busybox AS t2
|
||||
RUN echo "Hello t2"
|
||||
|
||||
FROM busybox AS t3
|
||||
RUN echo "Hello t3"
|
||||
@@ -0,0 +1,17 @@
|
||||
group "default" {
|
||||
targets = ["t1", "t2", "t3"]
|
||||
}
|
||||
|
||||
target "t1" {
|
||||
target = "t1"
|
||||
}
|
||||
|
||||
target "t2" {
|
||||
target = "t2"
|
||||
attest = ["type=provenance,mode=min"]
|
||||
}
|
||||
|
||||
target "t3" {
|
||||
target = "t3"
|
||||
attest = ["type=sbom"]
|
||||
}
|
||||
@@ -37,3 +37,13 @@ target "app-plus" {
|
||||
IAMPLUS = "true"
|
||||
}
|
||||
}
|
||||
|
||||
target "app-proxy" {
|
||||
inherits = ["app"]
|
||||
dockerfile = "proxy.Dockerfile"
|
||||
}
|
||||
|
||||
target "app-entitlements" {
|
||||
inherits = ["app"]
|
||||
entitlements = ["network.host"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM golang:alpine AS base
|
||||
ENV CGO_ENABLED=0
|
||||
RUN apk add --no-cache file git
|
||||
WORKDIR /src
|
||||
|
||||
FROM base AS build
|
||||
RUN --mount=type=bind,target=/src \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -ldflags "-s -w" -o /usr/bin/app .
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /usr/bin/app /bin/app
|
||||
|
||||
FROM alpine AS image
|
||||
COPY --from=build /usr/bin/app /bin/app
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/bin/app"]
|
||||
@@ -0,0 +1,17 @@
|
||||
variable "DESTDIR" {
|
||||
default = "/tmp/bake-build"
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["binary"]
|
||||
}
|
||||
|
||||
target "binary" {
|
||||
target = "binary"
|
||||
output = [DESTDIR]
|
||||
}
|
||||
|
||||
target "image" {
|
||||
target = "image"
|
||||
tags = ["localhost:5000/name/app:latest"]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module github.com/docker/bake-action/test/go
|
||||
|
||||
go 1.18
|
||||
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello, Go!")
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
group "validate" {
|
||||
targets = ["lint", "validate-vendor", "validate-doctoc"]
|
||||
}
|
||||
|
||||
target "lint" {
|
||||
name = "lint-${buildtags.name}"
|
||||
dockerfile = "./hack/dockerfiles/lint.Dockerfile"
|
||||
target = buildtags.target
|
||||
output = ["type=cacheonly"]
|
||||
matrix = {
|
||||
buildtags = [
|
||||
{ name = "default", tags = "", target = "golangci-lint" },
|
||||
{ name = "labs", tags = "dfrunsecurity dfparents", target = "golangci-lint" },
|
||||
{ name = "nydus", tags = "nydus", target = "golangci-lint" },
|
||||
{ name = "yaml", tags = "", target = "yamllint" },
|
||||
{ name = "proto", tags = "", target = "protolint" },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
target "validate-vendor" {
|
||||
dockerfile = "./hack/dockerfiles/vendor.Dockerfile"
|
||||
target = "validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "validate-doctoc" {
|
||||
dockerfile = "./hack/dockerfiles/doctoc.Dockerfile"
|
||||
target = "validate-toc"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
group "validate" {
|
||||
targets = ["lint", "lint-gopls", "validate-vendor", "validate-docs"]
|
||||
}
|
||||
|
||||
target "lint" {
|
||||
dockerfile = "./hack/dockerfiles/lint.Dockerfile"
|
||||
output = ["type=cacheonly"]
|
||||
platforms = [
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"linux/amd64",
|
||||
"linux/arm64",
|
||||
"linux/s390x",
|
||||
"linux/ppc64le",
|
||||
"linux/riscv64",
|
||||
"windows/amd64",
|
||||
"windows/arm64"
|
||||
]
|
||||
}
|
||||
|
||||
target "lint-gopls" {
|
||||
inherits = ["lint"]
|
||||
target = "gopls-analyze"
|
||||
}
|
||||
|
||||
target "validate-vendor" {
|
||||
dockerfile = "./hack/dockerfiles/vendor.Dockerfile"
|
||||
target = "validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "validate-docs" {
|
||||
dockerfile = "./hack/dockerfiles/docs.Dockerfile"
|
||||
target = "validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM busybox AS t1
|
||||
RUN echo "Hello t1"
|
||||
|
||||
FROM busybox AS t2
|
||||
RUN echo "Hello t2"
|
||||
@@ -0,0 +1,11 @@
|
||||
group "default" {
|
||||
targets = ["t1", "t2"]
|
||||
}
|
||||
|
||||
target "t1" {
|
||||
target = "t1"
|
||||
}
|
||||
|
||||
target "t2" {
|
||||
target = "t2"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
frOM busybox as base
|
||||
cOpy lint-other.Dockerfile .
|
||||
|
||||
froM busybox aS notused
|
||||
COPY lint-other.Dockerfile .
|
||||
|
||||
from scratch
|
||||
COPy --from=base \
|
||||
/lint-other.Dockerfile \
|
||||
/
|
||||
@@ -0,0 +1,12 @@
|
||||
frOM busybox as base
|
||||
cOpy lint.Dockerfile .
|
||||
|
||||
from scratch
|
||||
MAINTAINER moby@example.com
|
||||
COPy --from=base \
|
||||
/lint.Dockerfile \
|
||||
/
|
||||
|
||||
CMD [ "echo", "Hello, Norway!" ]
|
||||
CMD [ "echo", "Hello, Sweden!" ]
|
||||
ENTRYPOINT my-program start
|
||||
@@ -0,0 +1,12 @@
|
||||
group "default" {
|
||||
targets = ["lint", "lint-other", "lint-inline"]
|
||||
}
|
||||
target "lint" {
|
||||
dockerfile = "lint.Dockerfile"
|
||||
}
|
||||
target "lint-other" {
|
||||
dockerfile = "lint-other.Dockerfile"
|
||||
}
|
||||
target "lint-inline" {
|
||||
dockerfile-inline = "FRoM alpine\nENTRYPOINT [\"echo\", \"hello\"]"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
group "default" {
|
||||
targets = ["t3"]
|
||||
}
|
||||
|
||||
target "t3" {
|
||||
name = "${item.tag}"
|
||||
matrix = {
|
||||
item = t3
|
||||
}
|
||||
args = {
|
||||
VERSION = "${item.version}"
|
||||
DUMMY_ARG = "${item.arg}"
|
||||
}
|
||||
tags = ["${item.tag}"]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"t3": [
|
||||
{
|
||||
"version": "v1",
|
||||
"arg": "v1-value",
|
||||
"tag": "v1-tag"
|
||||
},
|
||||
{
|
||||
"version": "v2",
|
||||
"arg": "v2-value",
|
||||
"tag": "v2-tag"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM alpine
|
||||
RUN apk add --no-cache curl net-tools
|
||||
ARG HTTP_PROXY
|
||||
ARG HTTPS_PROXY
|
||||
RUN printenv HTTP_PROXY
|
||||
RUN printenv HTTPS_PROXY
|
||||
RUN netstat -aptn
|
||||
RUN curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy $HTTP_PROXY -v --insecure --head https://www.google.com
|
||||
+6
-8
@@ -1,19 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"esModuleInterop": true,
|
||||
"newLine": "lf",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"resolveJsonModule": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.test.ts",
|
||||
"jest.config.ts"
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import {defineConfig} from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
clearMocks: true,
|
||||
environment: 'node',
|
||||
setupFiles: ['./__tests__/setup.unit.ts'],
|
||||
include: ['**/*.test.ts'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['clover'],
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: ['src/**/main.ts']
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user