mirror of
https://github.com/hoverkraft-tech/compose-action.git
synced 2026-07-03 20:22:51 +08:00
feat: support OCI artifact compose-file inputs
Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
This commit is contained in:
parent
b542f028fa
commit
d2bee4f07e
42
.github/workflows/__check-action.yml
vendored
42
.github/workflows/__check-action.yml
vendored
@ -170,6 +170,14 @@ jobs:
|
||||
docker compose -f ./test/docker-compose.yml ps | grep test-service-a-1 || (echo "Service service-a is not running under custom context" && exit 1)
|
||||
(docker compose -f ./test/docker-compose.yml ps | grep test-service-b-1 && echo "Service service-b should not be running without profile" && exit 1) || true
|
||||
|
||||
- name: Given OCI compose artifact when running action
|
||||
assertion-name: "Then the OCI compose application runs"
|
||||
compose-file: oci://localhost:5000/compose-action-test:latest
|
||||
publish-oci-artifact: true
|
||||
source-compose-file: ./test/docker-compose.yml
|
||||
assertion: |
|
||||
docker compose -f "$OCI_COMPOSE_FILE" ps service-a | grep service-a | grep "Up" || (echo "Service service-a is not running from the OCI artifact" && exit 1)
|
||||
|
||||
env:
|
||||
DOCKER_COMPOSE_VERSION: ${{ matrix.expected-compose-version || '' }}
|
||||
steps:
|
||||
@ -200,6 +208,39 @@ jobs:
|
||||
|
||||
core.exportVariable('DOCKER_COMPOSE_VERSION', dockerComposeVersion);
|
||||
|
||||
- name: "Arrange: start local OCI registry"
|
||||
if: ${{ matrix.publish-oci-artifact }}
|
||||
# Keep the registry alive until the job ends because the action post hook
|
||||
# reuses the OCI reference for docker compose logs and down.
|
||||
run: |
|
||||
OCI_REGISTRY_IMAGE=registry:2.8.3
|
||||
OCI_REGISTRY_MAX_RETRIES=10
|
||||
OCI_REGISTRY_RETRY_DELAY_SECONDS=1
|
||||
|
||||
# Keep the registry on port 5000 so it matches the OCI reference configured in the test matrix.
|
||||
OCI_REGISTRY_CONTAINER_ID=$(docker run -d -p 5000:5000 "$OCI_REGISTRY_IMAGE")
|
||||
echo "OCI_REGISTRY_CONTAINER_ID=$OCI_REGISTRY_CONTAINER_ID" >> "$GITHUB_ENV"
|
||||
|
||||
retry_count=0
|
||||
while [ "$retry_count" -lt "$OCI_REGISTRY_MAX_RETRIES" ]; do
|
||||
if curl --fail --silent http://localhost:5000/v2/ >/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
sleep "$OCI_REGISTRY_RETRY_DELAY_SECONDS"
|
||||
done
|
||||
|
||||
echo "Local OCI registry did not become ready on localhost:5000"
|
||||
exit 1
|
||||
|
||||
- name: "Arrange: publish compose application as OCI artifact"
|
||||
if: ${{ matrix.publish-oci-artifact }}
|
||||
run: |
|
||||
OCI_REPOSITORY="${{ matrix.compose-file }}"
|
||||
OCI_PUBLISH_TARGET="${OCI_REPOSITORY#oci://}"
|
||||
docker compose -f "${{ matrix.source-compose-file }}" publish "$OCI_PUBLISH_TARGET"
|
||||
|
||||
- name: "Arrange: ensure original docker compose version is not the expected one"
|
||||
if: ${{ matrix.ensure-version-mismatch }}
|
||||
run: |
|
||||
@ -230,3 +271,4 @@ jobs:
|
||||
run: ${{ matrix.assertion }}
|
||||
env:
|
||||
IMAGE_NAME: ${{ matrix.image-name || '' }}
|
||||
OCI_COMPOSE_FILE: ${{ matrix.compose-file || '' }}
|
||||
|
||||
32
README.md
32
README.md
@ -54,7 +54,7 @@ Some extra options can be passed to the `docker compose down` command using the
|
||||
# Additional options to pass to `docker` command.
|
||||
docker-flags: ""
|
||||
|
||||
# Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd).
|
||||
# Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd), or an OCI artifact reference starting with `oci://`.
|
||||
# Default: `./docker-compose.yml`
|
||||
compose-file: ./docker-compose.yml
|
||||
|
||||
@ -96,21 +96,21 @@ Some extra options can be passed to the `docker compose down` command using the
|
||||
|
||||
## Inputs
|
||||
|
||||
| **Input** | **Description** | **Required** | **Default** |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------- |
|
||||
| **`docker-flags`** | Additional options to pass to `docker` command. | **false** | - |
|
||||
| **`compose-file`** | Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd). | **false** | `./docker-compose.yml` |
|
||||
| **`services`** | Services to perform `docker compose up`. | **false** | - |
|
||||
| **`up-flags`** | Additional options to pass to `docker compose up` command. | **false** | - |
|
||||
| **`down-flags`** | Additional options to pass to `docker compose down` command. | **false** | - |
|
||||
| **`compose-flags`** | Additional options to pass to `docker compose` command. | **false** | - |
|
||||
| **`cwd`** | Current working directory | **false** | `${{ github.workspace }}` |
|
||||
| **`compose-version`** | Compose version to use. | **false** | - |
|
||||
| | If null (default), it will use the current installed version. | | |
|
||||
| | If "latest", it will install the latest version. | | |
|
||||
| **`services-log-level`** | The log level used for Docker Compose service logs. | **false** | `debug` |
|
||||
| | Can be one of "debug", "info". | | |
|
||||
| **`github-token`** | The GitHub token used to create an authenticated client (to fetch the latest version of Docker Compose). | **false** | `${{ github.token }}` |
|
||||
| **Input** | **Description** | **Required** | **Default** |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------- |
|
||||
| **`docker-flags`** | Additional options to pass to `docker` command. | **false** | - |
|
||||
| **`compose-file`** | Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd), or an OCI artifact reference starting with `oci://`. | **false** | `./docker-compose.yml` |
|
||||
| **`services`** | Services to perform `docker compose up`. | **false** | - |
|
||||
| **`up-flags`** | Additional options to pass to `docker compose up` command. | **false** | - |
|
||||
| **`down-flags`** | Additional options to pass to `docker compose down` command. | **false** | - |
|
||||
| **`compose-flags`** | Additional options to pass to `docker compose` command. | **false** | - |
|
||||
| **`cwd`** | Current working directory | **false** | `${{ github.workspace }}` |
|
||||
| **`compose-version`** | Compose version to use. | **false** | - |
|
||||
| | If null (default), it will use the current installed version. | | |
|
||||
| | If "latest", it will install the latest version. | | |
|
||||
| **`services-log-level`** | The log level used for Docker Compose service logs. | **false** | `debug` |
|
||||
| | Can be one of "debug", "info". | | |
|
||||
| **`github-token`** | The GitHub token used to create an authenticated client (to fetch the latest version of Docker Compose). | **false** | `${{ github.token }}` |
|
||||
|
||||
<!-- inputs:end -->
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ inputs:
|
||||
description: "Additional options to pass to `docker` command."
|
||||
required: false
|
||||
compose-file:
|
||||
description: "Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd)."
|
||||
description: "Path to compose file(s). It can be a list of files. It can be absolute or relative to the current working directory (cwd), or an OCI artifact reference starting with `oci://`."
|
||||
required: false
|
||||
default: "./docker-compose.yml"
|
||||
services:
|
||||
|
||||
6
dist/index.js
generated
vendored
6
dist/index.js
generated
vendored
@ -43808,9 +43808,13 @@ class InputService {
|
||||
getComposeFiles() {
|
||||
const cwd = this.getCwd();
|
||||
const composeFiles = getMultilineInput(InputNames.ComposeFile).filter((composeFile) => {
|
||||
if (!composeFile.trim().length) {
|
||||
const trimmedComposeFile = composeFile.trim();
|
||||
if (!trimmedComposeFile.length) {
|
||||
return false;
|
||||
}
|
||||
if (trimmedComposeFile.startsWith("oci://")) {
|
||||
return true;
|
||||
}
|
||||
const possiblePaths = [(0,external_node_path_namespaceObject.join)(cwd, composeFile), composeFile];
|
||||
for (const path of possiblePaths) {
|
||||
if ((0,external_node_fs_namespaceObject.existsSync)(path)) {
|
||||
|
||||
6
dist/post.js
generated
vendored
6
dist/post.js
generated
vendored
@ -40060,9 +40060,13 @@ class InputService {
|
||||
getComposeFiles() {
|
||||
const cwd = this.getCwd();
|
||||
const composeFiles = getMultilineInput(InputNames.ComposeFile).filter((composeFile) => {
|
||||
if (!composeFile.trim().length) {
|
||||
const trimmedComposeFile = composeFile.trim();
|
||||
if (!trimmedComposeFile.length) {
|
||||
return false;
|
||||
}
|
||||
if (trimmedComposeFile.startsWith("oci://")) {
|
||||
return true;
|
||||
}
|
||||
const possiblePaths = [(0,external_node_path_namespaceObject.join)(cwd, composeFile), composeFile];
|
||||
for (const path of possiblePaths) {
|
||||
if ((0,external_node_fs_namespaceObject.existsSync)(path)) {
|
||||
|
||||
@ -139,6 +139,31 @@ describe("InputService", () => {
|
||||
expect(inputs.composeFiles).toEqual(["./compose.yml"]);
|
||||
});
|
||||
|
||||
it("should accept OCI compose files without checking the file system", () => {
|
||||
getMultilineInputMock.mockImplementation((inputName) => {
|
||||
switch (inputName) {
|
||||
case InputNames.ComposeFile:
|
||||
return ["oci://docker.io/hoverkraft/compose-app:latest"];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
getInputMock.mockImplementation((inputName) => {
|
||||
switch (inputName) {
|
||||
case InputNames.Cwd:
|
||||
return "/current/working/directory";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
const inputs = service.getInputs();
|
||||
|
||||
expect(inputs.composeFiles).toEqual(["oci://docker.io/hoverkraft/compose-app:latest"]);
|
||||
expect(existsSyncMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should throws an error when a compose file does not exist", () => {
|
||||
getMultilineInputMock.mockImplementation((inputName) => {
|
||||
switch (inputName) {
|
||||
|
||||
@ -54,10 +54,16 @@ export class InputService {
|
||||
private getComposeFiles(): string[] {
|
||||
const cwd = this.getCwd();
|
||||
const composeFiles = getMultilineInput(InputNames.ComposeFile).filter((composeFile: string) => {
|
||||
if (!composeFile.trim().length) {
|
||||
const trimmedComposeFile = composeFile.trim();
|
||||
|
||||
if (!trimmedComposeFile.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trimmedComposeFile.startsWith("oci://")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const possiblePaths = [join(cwd, composeFile), composeFile];
|
||||
|
||||
for (const path of possiblePaths) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user