mirror of
https://github.com/docker/build-push-action
synced 2024-11-22 18:31:40 +00:00
Handle build bake through bake, bake-files and bake-targets
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
b07bd1f9df
commit
8be103ff82
9 changed files with 475 additions and 241 deletions
44
.github/workflows/ci.yml
vendored
44
.github/workflows/ci.yml
vendored
|
@ -54,4 +54,48 @@ jobs:
|
||||||
localhost:5000/name/app:1.0.0
|
localhost:5000/name/app:1.0.0
|
||||||
-
|
-
|
||||||
name: Dump context
|
name: Dump context
|
||||||
|
if: always()
|
||||||
|
uses: crazy-max/ghaction-dump-context@v1
|
||||||
|
|
||||||
|
bake:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target:
|
||||||
|
- default
|
||||||
|
- release
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Run local registry
|
||||||
|
run: |
|
||||||
|
docker run -d -p 5000:5000 registry:2
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2.3.1
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: ./setup-qemu/ # change to docker/setup-qemu-action@master
|
||||||
|
with:
|
||||||
|
platforms: all
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: ./setup-buildx/ # change to docker/setup-buildx-action@master
|
||||||
|
# with:
|
||||||
|
# driver-opt: network=host
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
bake: true
|
||||||
|
#push: true
|
||||||
|
bake-files: |
|
||||||
|
./test/config.hcl
|
||||||
|
bake-targets: |
|
||||||
|
${{ matrix.target }}
|
||||||
|
-
|
||||||
|
name: Dump context
|
||||||
|
if: always()
|
||||||
uses: crazy-max/ghaction-dump-context@v1
|
uses: crazy-max/ghaction-dump-context@v1
|
||||||
|
|
78
README.md
78
README.md
|
@ -66,6 +66,59 @@ jobs:
|
||||||
user/app:1.0.0
|
user/app:1.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Bake
|
||||||
|
|
||||||
|
[Buildx bake](https://github.com/docker/buildx#buildx-bake-options-target) is also available with this action through
|
||||||
|
the [`bake` inputs](#inputs).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: master
|
||||||
|
push:
|
||||||
|
branches: master
|
||||||
|
tags:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
buildx:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
with:
|
||||||
|
platforms: all
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
with:
|
||||||
|
install: true
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
push: true
|
||||||
|
bake: true
|
||||||
|
bake-files: |
|
||||||
|
./config.hcl
|
||||||
|
bake-targets: |
|
||||||
|
default
|
||||||
|
release
|
||||||
|
```
|
||||||
|
|
||||||
## Customizing
|
## Customizing
|
||||||
|
|
||||||
### inputs
|
### inputs
|
||||||
|
@ -74,22 +127,25 @@ Following inputs can be used as `step.with` keys
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|---------------------|---------|-----------------------------------|------------------------------------|
|
|---------------------|---------|-----------------------------------|------------------------------------|
|
||||||
| `builder` | String | | Builder instance |
|
| `builder` | String | | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
|
||||||
| `context` | String | `.` | Build's context is the set of files located in the specified `PATH` or `URL` |
|
| `context` | String | `.` | Build's context is the set of files located in the specified `PATH` or `URL` |
|
||||||
| `file` | String | `./Dockerfile` | Path to the Dockerfile. |
|
| `file` | String | `./Dockerfile` | Path to the Dockerfile. |
|
||||||
| `build-args` | String | | Newline-delimited list of build-time variables |
|
| `build-args` | List | | Newline-delimited list of build-time variables |
|
||||||
| `labels` | String | | Newline-delimited list of metadata for an image |
|
| `labels` | List | | Newline-delimited list of metadata for an image |
|
||||||
| `tags` | String | | Newline-delimited list of tags **required** |
|
| `tags` | List | | Newline-delimited list of tags |
|
||||||
| `pull` | Bool | `false` | Always attempt to pull a newer version of the image |
|
| `pull` | Bool | `false` | Always attempt to pull a newer version of the image |
|
||||||
| `target` | String | | Sets the target stage to build |
|
| `target` | String | | Sets the target stage to build |
|
||||||
| `allow` | String | | Allow extra privileged entitlement (eg. network.host,security.insecure) |
|
| `allow` | String | | [Allow](https://github.com/docker/buildx#--allowentitlement) extra privileged entitlement (eg. network.host,security.insecure) |
|
||||||
| `no-cache` | Bool | `false` | Do not use cache when building the image |
|
| `no-cache` | Bool | `false` | Do not use cache when building the image |
|
||||||
| `platforms` | String | | Comma-delimited list of target platforms for build |
|
| `platforms` | String | | Comma-delimited list of [target platforms](https://github.com/docker/buildx#---platformvaluevalue) for build |
|
||||||
| `load` | Bool | `false` | Shorthand for `--output=type=docker` |
|
| `load` | Bool | `false` | [Load](https://github.com/docker/buildx#--load) is a shorthand for `--output=type=docker` |
|
||||||
| `push` | Bool | `false` | Shorthand for `--output=type=registry` |
|
| `push` | Bool | `false` | [Push](https://github.com/docker/buildx#--push) is a shorthand for `--output=type=registry` |
|
||||||
| `outputs` | String | | Newline-delimited list of output destinations (format: `type=local,dest=path`) |
|
| `outputs` | List | | Newline-delimited list of [output destinations](https://github.com/docker/buildx#-o---outputpath-typetypekeyvalue) (format: `type=local,dest=path`) |
|
||||||
| `cache-from` | String | | Newline-delimited list of external cache sources (eg. `user/app:cache`, `type=local,src=path/to/dir`) |
|
| `cache-from` | List | | Newline-delimited list of [external cache sources](https://github.com/docker/buildx#--cache-fromnametypetypekeyvalue) (eg. `user/app:cache`, `type=local,src=path/to/dir`) |
|
||||||
| `cache-to` | String | | Newline-delimited list of cache export destinations (eg. `user/app:cache`, `type=local,dest=path/to/dir`) |
|
| `cache-to` | List | | Newline-delimited list of [cache export destinations](https://github.com/docker/buildx#--cache-tonametypetypekeyvalue) (eg. `user/app:cache`, `type=local,dest=path/to/dir`) |
|
||||||
|
| `bake` | Bool | `false` | Use [bake](https://github.com/docker/buildx#buildx-bake-options-target) as the high-level build command |
|
||||||
|
| `bake-files` | List | | Newline-delimited list of [bake definition files](https://github.com/docker/buildx#file-definition) |
|
||||||
|
| `bake-targets` | List | | Newline-delimited list of bake targets |
|
||||||
|
|
||||||
### outputs
|
### outputs
|
||||||
|
|
||||||
|
|
16
action.yml
16
action.yml
|
@ -25,7 +25,7 @@ inputs:
|
||||||
required: false
|
required: false
|
||||||
tags:
|
tags:
|
||||||
description: "Newline-delimited list of tags"
|
description: "Newline-delimited list of tags"
|
||||||
required: true
|
required: false
|
||||||
pull:
|
pull:
|
||||||
description: "Always attempt to pull a newer version of the image"
|
description: "Always attempt to pull a newer version of the image"
|
||||||
required: false
|
required: false
|
||||||
|
@ -44,11 +44,11 @@ inputs:
|
||||||
description: "Comma-delimited list of target platforms for build"
|
description: "Comma-delimited list of target platforms for build"
|
||||||
required: false
|
required: false
|
||||||
load:
|
load:
|
||||||
description: "Shorthand for --output=type=docker"
|
description: "Load is a shorthand for --output=type=docker"
|
||||||
required: false
|
required: false
|
||||||
default: 'false'
|
default: 'false'
|
||||||
push:
|
push:
|
||||||
description: "Shorthand for --output=type=registry"
|
description: "Push is a shorthand for --output=type=registry"
|
||||||
required: false
|
required: false
|
||||||
default: 'false'
|
default: 'false'
|
||||||
outputs:
|
outputs:
|
||||||
|
@ -60,6 +60,16 @@ inputs:
|
||||||
cache-to:
|
cache-to:
|
||||||
description: "Newline-delimited list of cache export destinations for buildx (eg. user/app:cache, type=local,dest=path/to/dir)"
|
description: "Newline-delimited list of cache export destinations for buildx (eg. user/app:cache, type=local,dest=path/to/dir)"
|
||||||
required: false
|
required: false
|
||||||
|
bake:
|
||||||
|
description: "Use bake as the high-level build command"
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
bake-files:
|
||||||
|
description: "Newline-delimited list of bake definition files"
|
||||||
|
required: false
|
||||||
|
bake-targets:
|
||||||
|
description: "Newline-delimited list of bake targets"
|
||||||
|
required: false
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
digest:
|
digest:
|
||||||
|
|
290
dist/index.js
generated
vendored
290
dist/index.js
generated
vendored
|
@ -1003,7 +1003,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const os = __importStar(__webpack_require__(87));
|
const os = __importStar(__webpack_require__(87));
|
||||||
const buildx = __importStar(__webpack_require__(982));
|
const buildx = __importStar(__webpack_require__(982));
|
||||||
const context_helper_1 = __webpack_require__(338);
|
const context_1 = __webpack_require__(482);
|
||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(470));
|
||||||
const exec = __importStar(__webpack_require__(986));
|
const exec = __importStar(__webpack_require__(986));
|
||||||
function run() {
|
function run() {
|
||||||
|
@ -1013,149 +1013,28 @@ function run() {
|
||||||
core.setFailed('Only supported on linux platform');
|
core.setFailed('Only supported on linux platform');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const inputs = yield context_helper_1.loadInputs();
|
|
||||||
if (!(yield buildx.isAvailable())) {
|
if (!(yield buildx.isAvailable())) {
|
||||||
core.setFailed(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
core.setFailed(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let buildArgs = ['buildx', 'build'];
|
const inputs = yield context_1.getInputs();
|
||||||
if (inputs.builder) {
|
if (inputs.builder) {
|
||||||
core.info(`📌 Using builder instance ${inputs.builder}`);
|
core.info(`📌 Using builder instance ${inputs.builder}`);
|
||||||
yield buildx.use(inputs.builder);
|
yield buildx.use(inputs.builder);
|
||||||
}
|
}
|
||||||
if (inputs.file) {
|
|
||||||
buildArgs.push('--file', inputs.file);
|
|
||||||
}
|
|
||||||
yield asyncForEach(inputs.buildArgs, (buildArg) => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
buildArgs.push('--build-arg', buildArg);
|
|
||||||
}));
|
|
||||||
yield asyncForEach(inputs.labels, (label) => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
buildArgs.push('--label', label);
|
|
||||||
}));
|
|
||||||
yield asyncForEach(inputs.tags, (tag) => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
buildArgs.push('--tag', tag);
|
|
||||||
}));
|
|
||||||
if (inputs.pull) {
|
|
||||||
buildArgs.push('--pull');
|
|
||||||
}
|
|
||||||
if (inputs.target) {
|
|
||||||
buildArgs.push('--target', inputs.target);
|
|
||||||
}
|
|
||||||
if (inputs.allow) {
|
|
||||||
buildArgs.push('--allow', inputs.allow);
|
|
||||||
}
|
|
||||||
if (inputs.noCache) {
|
|
||||||
buildArgs.push('--no-cache');
|
|
||||||
}
|
|
||||||
if (inputs.platforms) {
|
|
||||||
buildArgs.push('--platform', inputs.platforms);
|
|
||||||
}
|
|
||||||
if (inputs.load) {
|
|
||||||
buildArgs.push('--load');
|
|
||||||
}
|
|
||||||
if (inputs.push) {
|
|
||||||
buildArgs.push('--push');
|
|
||||||
}
|
|
||||||
yield asyncForEach(inputs.outputs, (output) => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
buildArgs.push('--output', output);
|
|
||||||
}));
|
|
||||||
yield asyncForEach(inputs.cacheFrom, (cacheFrom) => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
buildArgs.push('--cache-from', cacheFrom);
|
|
||||||
}));
|
|
||||||
yield asyncForEach(inputs.cacheTo, (cacheTo) => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
buildArgs.push('--cache-from', cacheTo);
|
|
||||||
}));
|
|
||||||
buildArgs.push(inputs.context);
|
|
||||||
core.info(`🏃 Starting build...`);
|
core.info(`🏃 Starting build...`);
|
||||||
yield exec.exec('docker', buildArgs);
|
yield exec.exec('docker', yield context_1.getArgs(inputs));
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const asyncForEach = (array, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
|
||||||
for (let index = 0; index < array.length; index++) {
|
|
||||||
yield callback(array[index], index, array);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
run();
|
run();
|
||||||
//# sourceMappingURL=main.js.map
|
//# sourceMappingURL=main.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 338:
|
|
||||||
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.loadInputs = void 0;
|
|
||||||
const core = __importStar(__webpack_require__(470));
|
|
||||||
function loadInputs() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
return {
|
|
||||||
context: core.getInput('context') || '.',
|
|
||||||
file: core.getInput('file') || './Dockerfile',
|
|
||||||
buildArgs: yield getInputList('build-args'),
|
|
||||||
labels: yield getInputList('labels'),
|
|
||||||
tags: yield getInputList('tags'),
|
|
||||||
pull: /true/i.test(core.getInput('pull')),
|
|
||||||
target: core.getInput('target'),
|
|
||||||
allow: core.getInput('allow'),
|
|
||||||
noCache: /true/i.test(core.getInput('no-cache')),
|
|
||||||
builder: core.getInput('builder'),
|
|
||||||
platforms: core.getInput('platforms'),
|
|
||||||
load: /true/i.test(core.getInput('load')),
|
|
||||||
push: /true/i.test(core.getInput('push')),
|
|
||||||
outputs: yield getInputList('outputs'),
|
|
||||||
cacheFrom: yield getInputList('cache-from'),
|
|
||||||
cacheTo: yield getInputList('cache-to')
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
exports.loadInputs = loadInputs;
|
|
||||||
function getInputList(name) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const items = core.getInput(name);
|
|
||||||
if (items == '') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return items.split(/\r?\n/).reduce((acc, line) => acc.concat(line.split(',')).map(pat => pat.trim()), []);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=context-helper.js.map
|
|
||||||
|
|
||||||
/***/ }),
|
|
||||||
|
|
||||||
/***/ 357:
|
/***/ 357:
|
||||||
/***/ (function(module) {
|
/***/ (function(module) {
|
||||||
|
|
||||||
|
@ -1491,6 +1370,169 @@ exports.getState = getState;
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 482:
|
||||||
|
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.getArgs = exports.getInputs = void 0;
|
||||||
|
const core = __importStar(__webpack_require__(470));
|
||||||
|
function getInputs() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
return {
|
||||||
|
context: core.getInput('context') || '.',
|
||||||
|
file: core.getInput('file') || './Dockerfile',
|
||||||
|
buildArgs: yield getInputList('build-args'),
|
||||||
|
labels: yield getInputList('labels'),
|
||||||
|
tags: yield getInputList('tags'),
|
||||||
|
pull: /true/i.test(core.getInput('pull')),
|
||||||
|
target: core.getInput('target'),
|
||||||
|
allow: core.getInput('allow'),
|
||||||
|
noCache: /true/i.test(core.getInput('no-cache')),
|
||||||
|
builder: core.getInput('builder'),
|
||||||
|
platforms: core.getInput('platforms'),
|
||||||
|
load: /true/i.test(core.getInput('load')),
|
||||||
|
push: /true/i.test(core.getInput('push')),
|
||||||
|
outputs: yield getInputList('outputs'),
|
||||||
|
cacheFrom: yield getInputList('cache-from'),
|
||||||
|
cacheTo: yield getInputList('cache-to'),
|
||||||
|
bake: /true/i.test(core.getInput('bake')),
|
||||||
|
bakeFiles: yield getInputList('bake-files'),
|
||||||
|
bakeTargets: yield getInputList('bake-targets')
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.getInputs = getInputs;
|
||||||
|
function getArgs(inputs) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let args = ['buildx'];
|
||||||
|
if (inputs.bake) {
|
||||||
|
args.concat(yield getBakeArgs(inputs));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args.concat(yield getBuildArgs(inputs));
|
||||||
|
}
|
||||||
|
args.concat(yield getCommonArgs(inputs));
|
||||||
|
if (!inputs.bake) {
|
||||||
|
args.push(inputs.context);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args.concat(inputs.bakeTargets);
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.getArgs = getArgs;
|
||||||
|
function getCommonArgs(inputs) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let args = [];
|
||||||
|
if (inputs.noCache) {
|
||||||
|
args.push('--no-cache');
|
||||||
|
}
|
||||||
|
if (inputs.pull) {
|
||||||
|
args.push('--pull');
|
||||||
|
}
|
||||||
|
if (inputs.load) {
|
||||||
|
args.push('--load');
|
||||||
|
}
|
||||||
|
if (inputs.push) {
|
||||||
|
args.push('--push');
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getBakeArgs(inputs) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let args = ['bake'];
|
||||||
|
yield asyncForEach(inputs.bakeFiles, (bakeFile) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
args.push('--file', bakeFile);
|
||||||
|
}));
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getBuildArgs(inputs) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let args = ['build'];
|
||||||
|
yield asyncForEach(inputs.buildArgs, (buildArg) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
args.push('--build-arg', buildArg);
|
||||||
|
}));
|
||||||
|
yield asyncForEach(inputs.labels, (label) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
args.push('--label', label);
|
||||||
|
}));
|
||||||
|
yield asyncForEach(inputs.tags, (tag) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
args.push('--tag', tag);
|
||||||
|
}));
|
||||||
|
if (inputs.target) {
|
||||||
|
args.push('--target', inputs.target);
|
||||||
|
}
|
||||||
|
if (inputs.allow) {
|
||||||
|
args.push('--allow', inputs.allow);
|
||||||
|
}
|
||||||
|
if (inputs.platforms) {
|
||||||
|
args.push('--platform', inputs.platforms);
|
||||||
|
}
|
||||||
|
yield asyncForEach(inputs.outputs, (output) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
args.push('--output', output);
|
||||||
|
}));
|
||||||
|
yield asyncForEach(inputs.cacheFrom, (cacheFrom) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
args.push('--cache-from', cacheFrom);
|
||||||
|
}));
|
||||||
|
yield asyncForEach(inputs.cacheTo, (cacheTo) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
args.push('--cache-from', cacheTo);
|
||||||
|
}));
|
||||||
|
if (inputs.file) {
|
||||||
|
args.push('--file', inputs.file);
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getInputList(name) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const items = core.getInput(name);
|
||||||
|
if (items == '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return items.split(/\r?\n/).reduce((acc, line) => acc.concat(line.split(',')).map(pat => pat.trim()), []);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const asyncForEach = (array, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
|
for (let index = 0; index < array.length; index++) {
|
||||||
|
yield callback(array[index], index, array);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=context.js.map
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
/***/ 614:
|
/***/ 614:
|
||||||
/***/ (function(module) {
|
/***/ (function(module) {
|
||||||
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
import * as core from '@actions/core';
|
|
||||||
|
|
||||||
export interface Inputs {
|
|
||||||
context: string;
|
|
||||||
file: string;
|
|
||||||
buildArgs: string[];
|
|
||||||
labels: string[];
|
|
||||||
tags: string[];
|
|
||||||
pull: boolean;
|
|
||||||
target: string;
|
|
||||||
allow: string;
|
|
||||||
noCache: boolean;
|
|
||||||
builder: string;
|
|
||||||
platforms: string;
|
|
||||||
load: boolean;
|
|
||||||
push: boolean;
|
|
||||||
outputs: string[];
|
|
||||||
cacheFrom: string[];
|
|
||||||
cacheTo: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function loadInputs(): Promise<Inputs> {
|
|
||||||
return {
|
|
||||||
context: core.getInput('context') || '.',
|
|
||||||
file: core.getInput('file') || './Dockerfile',
|
|
||||||
buildArgs: await getInputList('build-args'),
|
|
||||||
labels: await getInputList('labels'),
|
|
||||||
tags: await getInputList('tags'),
|
|
||||||
pull: /true/i.test(core.getInput('pull')),
|
|
||||||
target: core.getInput('target'),
|
|
||||||
allow: core.getInput('allow'),
|
|
||||||
noCache: /true/i.test(core.getInput('no-cache')),
|
|
||||||
builder: core.getInput('builder'),
|
|
||||||
platforms: core.getInput('platforms'),
|
|
||||||
load: /true/i.test(core.getInput('load')),
|
|
||||||
push: /true/i.test(core.getInput('push')),
|
|
||||||
outputs: await getInputList('outputs'),
|
|
||||||
cacheFrom: await getInputList('cache-from'),
|
|
||||||
cacheTo: await getInputList('cache-to')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getInputList(name: string): Promise<string[]> {
|
|
||||||
const items = core.getInput(name);
|
|
||||||
if (items == '') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return items.split(/\r?\n/).reduce<string[]>((acc, line) => acc.concat(line.split(',')).map(pat => pat.trim()), []);
|
|
||||||
}
|
|
139
src/context.ts
Normal file
139
src/context.ts
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
|
export interface Inputs {
|
||||||
|
context: string;
|
||||||
|
file: string;
|
||||||
|
buildArgs: string[];
|
||||||
|
labels: string[];
|
||||||
|
tags: string[];
|
||||||
|
pull: boolean;
|
||||||
|
target: string;
|
||||||
|
allow: string;
|
||||||
|
noCache: boolean;
|
||||||
|
builder: string;
|
||||||
|
platforms: string;
|
||||||
|
load: boolean;
|
||||||
|
push: boolean;
|
||||||
|
outputs: string[];
|
||||||
|
cacheFrom: string[];
|
||||||
|
cacheTo: string[];
|
||||||
|
bake: boolean;
|
||||||
|
bakeFiles: string[];
|
||||||
|
bakeTargets: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getInputs(): Promise<Inputs> {
|
||||||
|
return {
|
||||||
|
context: core.getInput('context') || '.',
|
||||||
|
file: core.getInput('file') || './Dockerfile',
|
||||||
|
buildArgs: await getInputList('build-args'),
|
||||||
|
labels: await getInputList('labels'),
|
||||||
|
tags: await getInputList('tags'),
|
||||||
|
pull: /true/i.test(core.getInput('pull')),
|
||||||
|
target: core.getInput('target'),
|
||||||
|
allow: core.getInput('allow'),
|
||||||
|
noCache: /true/i.test(core.getInput('no-cache')),
|
||||||
|
builder: core.getInput('builder'),
|
||||||
|
platforms: core.getInput('platforms'),
|
||||||
|
load: /true/i.test(core.getInput('load')),
|
||||||
|
push: /true/i.test(core.getInput('push')),
|
||||||
|
outputs: await getInputList('outputs'),
|
||||||
|
cacheFrom: await getInputList('cache-from'),
|
||||||
|
cacheTo: await getInputList('cache-to'),
|
||||||
|
bake: /true/i.test(core.getInput('bake')),
|
||||||
|
bakeFiles: await getInputList('bake-files'),
|
||||||
|
bakeTargets: await getInputList('bake-targets')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getArgs(inputs: Inputs): Promise<string[]> {
|
||||||
|
let args: Array<string> = ['buildx'];
|
||||||
|
if (inputs.bake) {
|
||||||
|
args.concat(await getBakeArgs(inputs));
|
||||||
|
} else {
|
||||||
|
args.concat(await getBuildArgs(inputs));
|
||||||
|
}
|
||||||
|
args.concat(await getCommonArgs(inputs));
|
||||||
|
|
||||||
|
if (!inputs.bake) {
|
||||||
|
args.push(inputs.context);
|
||||||
|
} else {
|
||||||
|
args.concat(inputs.bakeTargets);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCommonArgs(inputs: Inputs): Promise<string[]> {
|
||||||
|
let args: Array<string> = [];
|
||||||
|
if (inputs.noCache) {
|
||||||
|
args.push('--no-cache');
|
||||||
|
}
|
||||||
|
if (inputs.pull) {
|
||||||
|
args.push('--pull');
|
||||||
|
}
|
||||||
|
if (inputs.load) {
|
||||||
|
args.push('--load');
|
||||||
|
}
|
||||||
|
if (inputs.push) {
|
||||||
|
args.push('--push');
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getBakeArgs(inputs: Inputs): Promise<string[]> {
|
||||||
|
let args: Array<string> = ['bake'];
|
||||||
|
await asyncForEach(inputs.bakeFiles, async bakeFile => {
|
||||||
|
args.push('--file', bakeFile);
|
||||||
|
});
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getBuildArgs(inputs: Inputs): Promise<string[]> {
|
||||||
|
let args: Array<string> = ['build'];
|
||||||
|
await asyncForEach(inputs.buildArgs, async buildArg => {
|
||||||
|
args.push('--build-arg', buildArg);
|
||||||
|
});
|
||||||
|
await asyncForEach(inputs.labels, async label => {
|
||||||
|
args.push('--label', label);
|
||||||
|
});
|
||||||
|
await asyncForEach(inputs.tags, async tag => {
|
||||||
|
args.push('--tag', tag);
|
||||||
|
});
|
||||||
|
if (inputs.target) {
|
||||||
|
args.push('--target', inputs.target);
|
||||||
|
}
|
||||||
|
if (inputs.allow) {
|
||||||
|
args.push('--allow', inputs.allow);
|
||||||
|
}
|
||||||
|
if (inputs.platforms) {
|
||||||
|
args.push('--platform', inputs.platforms);
|
||||||
|
}
|
||||||
|
await asyncForEach(inputs.outputs, async output => {
|
||||||
|
args.push('--output', output);
|
||||||
|
});
|
||||||
|
await asyncForEach(inputs.cacheFrom, async cacheFrom => {
|
||||||
|
args.push('--cache-from', cacheFrom);
|
||||||
|
});
|
||||||
|
await asyncForEach(inputs.cacheTo, async cacheTo => {
|
||||||
|
args.push('--cache-from', cacheTo);
|
||||||
|
});
|
||||||
|
if (inputs.file) {
|
||||||
|
args.push('--file', inputs.file);
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getInputList(name: string): Promise<string[]> {
|
||||||
|
const items = core.getInput(name);
|
||||||
|
if (items == '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return items.split(/\r?\n/).reduce<string[]>((acc, line) => acc.concat(line.split(',')).map(pat => pat.trim()), []);
|
||||||
|
}
|
||||||
|
|
||||||
|
const asyncForEach = async (array, callback) => {
|
||||||
|
for (let index = 0; index < array.length; index++) {
|
||||||
|
await callback(array[index], index, array);
|
||||||
|
}
|
||||||
|
};
|
57
src/main.ts
57
src/main.ts
|
@ -1,6 +1,6 @@
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as buildx from './buildx';
|
import * as buildx from './buildx';
|
||||||
import {Inputs, loadInputs} from './context-helper';
|
import {Inputs, getInputs, getArgs} from './context';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as exec from '@actions/exec';
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
|
@ -11,74 +11,23 @@ async function run(): Promise<void> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputs: Inputs = await loadInputs();
|
|
||||||
|
|
||||||
if (!(await buildx.isAvailable())) {
|
if (!(await buildx.isAvailable())) {
|
||||||
core.setFailed(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
core.setFailed(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let buildArgs: Array<string> = ['buildx', 'build'];
|
const inputs: Inputs = await getInputs();
|
||||||
|
|
||||||
if (inputs.builder) {
|
if (inputs.builder) {
|
||||||
core.info(`📌 Using builder instance ${inputs.builder}`);
|
core.info(`📌 Using builder instance ${inputs.builder}`);
|
||||||
await buildx.use(inputs.builder);
|
await buildx.use(inputs.builder);
|
||||||
}
|
}
|
||||||
if (inputs.file) {
|
|
||||||
buildArgs.push('--file', inputs.file);
|
|
||||||
}
|
|
||||||
await asyncForEach(inputs.buildArgs, async buildArg => {
|
|
||||||
buildArgs.push('--build-arg', buildArg);
|
|
||||||
});
|
|
||||||
await asyncForEach(inputs.labels, async label => {
|
|
||||||
buildArgs.push('--label', label);
|
|
||||||
});
|
|
||||||
await asyncForEach(inputs.tags, async tag => {
|
|
||||||
buildArgs.push('--tag', tag);
|
|
||||||
});
|
|
||||||
if (inputs.pull) {
|
|
||||||
buildArgs.push('--pull');
|
|
||||||
}
|
|
||||||
if (inputs.target) {
|
|
||||||
buildArgs.push('--target', inputs.target);
|
|
||||||
}
|
|
||||||
if (inputs.allow) {
|
|
||||||
buildArgs.push('--allow', inputs.allow);
|
|
||||||
}
|
|
||||||
if (inputs.noCache) {
|
|
||||||
buildArgs.push('--no-cache');
|
|
||||||
}
|
|
||||||
if (inputs.platforms) {
|
|
||||||
buildArgs.push('--platform', inputs.platforms);
|
|
||||||
}
|
|
||||||
if (inputs.load) {
|
|
||||||
buildArgs.push('--load');
|
|
||||||
}
|
|
||||||
if (inputs.push) {
|
|
||||||
buildArgs.push('--push');
|
|
||||||
}
|
|
||||||
await asyncForEach(inputs.outputs, async output => {
|
|
||||||
buildArgs.push('--output', output);
|
|
||||||
});
|
|
||||||
await asyncForEach(inputs.cacheFrom, async cacheFrom => {
|
|
||||||
buildArgs.push('--cache-from', cacheFrom);
|
|
||||||
});
|
|
||||||
await asyncForEach(inputs.cacheTo, async cacheTo => {
|
|
||||||
buildArgs.push('--cache-from', cacheTo);
|
|
||||||
});
|
|
||||||
buildArgs.push(inputs.context);
|
|
||||||
|
|
||||||
core.info(`🏃 Starting build...`);
|
core.info(`🏃 Starting build...`);
|
||||||
await exec.exec('docker', buildArgs);
|
await exec.exec('docker', await getArgs(inputs));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const asyncForEach = async (array, callback) => {
|
|
||||||
for (let index = 0; index < array.length; index++) {
|
|
||||||
await callback(array[index], index, array);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
4
test/Dockerfile-bake
Normal file
4
test/Dockerfile-bake
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
FROM alpine
|
||||||
|
|
||||||
|
ARG name=world
|
||||||
|
RUN echo "Hello ${name}!"
|
39
test/config.hcl
Normal file
39
test/config.hcl
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
group "default" {
|
||||||
|
targets = ["db", "app"]
|
||||||
|
}
|
||||||
|
|
||||||
|
group "release" {
|
||||||
|
targets = ["db", "app-plus"]
|
||||||
|
}
|
||||||
|
|
||||||
|
target "db" {
|
||||||
|
context = "./test"
|
||||||
|
tags = ["docker.io/tonistiigi/db"]
|
||||||
|
}
|
||||||
|
|
||||||
|
target "app" {
|
||||||
|
context = "./test"
|
||||||
|
dockerfile = "Dockerfile-bake"
|
||||||
|
args = {
|
||||||
|
name = "foo"
|
||||||
|
}
|
||||||
|
tags = [
|
||||||
|
"localhost:5000/name/app:latest",
|
||||||
|
"localhost:5000/name/app:1.0.0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
target "cross" {
|
||||||
|
platforms = [
|
||||||
|
"linux/amd64",
|
||||||
|
"linux/arm64",
|
||||||
|
"linux/386"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
target "app-plus" {
|
||||||
|
inherits = ["app", "cross"]
|
||||||
|
args = {
|
||||||
|
IAMPLUS = "true"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue