Skip to content

Commit 0c564a9

Browse files
committed
feat(docker): pin installed docker version
Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
1 parent 338e184 commit 0c564a9

4 files changed

Lines changed: 192 additions & 4 deletions

File tree

.github/workflows/__shared-ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ jobs:
3737
issues: read
3838
packages: write
3939
pull-requests: read
40+
test-action-docker-setup:
41+
needs: linter
42+
uses: ./.github/workflows/__test-action-docker-setup.yml
43+
permissions:
44+
contents: read
4045

4146
test-action-docker-prune-pull-requests-image-tags:
4247
needs: linter
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
name: Test for "docker/setup" action
3+
run-name: Test for "docker/setup" action
4+
5+
on: # yamllint disable-line rule:truthy
6+
workflow_call:
7+
8+
permissions: {}
9+
10+
jobs:
11+
tests:
12+
name: Test for "docker/setup" action
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
steps:
17+
- name: Arrange - Checkout
18+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
19+
with:
20+
persist-credentials: false
21+
22+
- name: Arrange - Ensure token is set
23+
run: |
24+
if [ -z "${{ github.token }}" ]; then
25+
echo "GitHub token is not set"
26+
exit 1
27+
fi
28+
29+
- name: Act - Setup Docker
30+
id: docker-setup
31+
uses: ./actions/docker/setup
32+
with:
33+
oci-registry: ghcr.io
34+
oci-registry-username: ${{ github.repository_owner }}
35+
oci-registry-password: ${{ github.token }}
36+
37+
- name: Assert - Check setup outputs and installed tooling
38+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
39+
env:
40+
EXPECTED_DOCKER_VERSION: 29.5.2
41+
PUSH_REGISTRY_OUTPUT: ${{ steps.docker-setup.outputs.push-registry }}
42+
CACHE_REGISTRY_OUTPUT: ${{ steps.docker-setup.outputs.cache-registry }}
43+
PULL_REGISTRIES_OUTPUT: ${{ steps.docker-setup.outputs.pull-registries }}
44+
BUILDX_NAME_OUTPUT: ${{ steps.docker-setup.outputs.buildx-name }}
45+
with:
46+
script: |
47+
const assert = require("assert");
48+
49+
assert.equal(process.env.PUSH_REGISTRY_OUTPUT, "ghcr.io", '"push-registry" output is not valid');
50+
assert.equal(process.env.CACHE_REGISTRY_OUTPUT, "ghcr.io", '"cache-registry" output is not valid');
51+
52+
let pullRegistries = null;
53+
try {
54+
pullRegistries = JSON.parse(process.env.PULL_REGISTRIES_OUTPUT);
55+
} catch (error) {
56+
assert.fail(`Failed to parse "pull-registries" output: ${error}`);
57+
}
58+
59+
assert.deepEqual(pullRegistries, ["ghcr.io"], '"pull-registries" output is not valid');
60+
61+
const buildxName = `${process.env.BUILDX_NAME_OUTPUT || ''}`.trim();
62+
assert(buildxName.length, '"buildx-name" output is empty');
63+
64+
const dockerVersionResult = await exec.getExecOutput(
65+
"docker",
66+
["version", "--format", "{{.Server.Version}}"],
67+
{ silent: true },
68+
);
69+
assert.equal(
70+
dockerVersionResult.stdout.trim(),
71+
process.env.EXPECTED_DOCKER_VERSION,
72+
'Installed Docker version is not the expected pinned version',
73+
);
74+
75+
const buildxVersionResult = await exec.getExecOutput(
76+
"docker",
77+
["buildx", "version"],
78+
{ silent: true },
79+
);
80+
assert(buildxVersionResult.stdout.trim().length, '"docker buildx version" returned an empty result');
81+
82+
const buildxInspectResult = await exec.getExecOutput(
83+
"docker",
84+
["buildx", "inspect", buildxName],
85+
{ ignoreReturnCode: true, silent: true },
86+
);
87+
assert.equal(buildxInspectResult.exitCode, 0, 'Configured Buildx builder is not inspectable');
88+
89+
tests-with-multiple-registries-and-no-buildx:
90+
name: Test for "docker/setup" action with multiple registries and no Buildx
91+
runs-on: ubuntu-latest
92+
permissions:
93+
contents: read
94+
steps:
95+
- name: Arrange - Checkout
96+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
97+
with:
98+
persist-credentials: false
99+
100+
- name: Arrange - Ensure token is set
101+
run: |
102+
if [ -z "${{ github.token }}" ]; then
103+
echo "GitHub token is not set"
104+
exit 1
105+
fi
106+
107+
- name: Act - Setup Docker
108+
id: docker-setup
109+
uses: ./actions/docker/setup
110+
with:
111+
oci-registry: |
112+
{"pull":"docker.io","pull:private":"ghcr.io","push":"ghcr.io"}
113+
oci-registry-username: |
114+
{"push":"${{ github.repository_owner }}"}
115+
oci-registry-password: |
116+
{"push":"${{ github.token }}"}
117+
setup-buildx: false
118+
119+
- name: Assert - Check registry outputs without Buildx
120+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
121+
env:
122+
EXPECTED_DOCKER_VERSION: 29.5.2
123+
PUSH_REGISTRY_OUTPUT: ${{ steps.docker-setup.outputs.push-registry }}
124+
CACHE_REGISTRY_OUTPUT: ${{ steps.docker-setup.outputs.cache-registry }}
125+
PULL_REGISTRIES_OUTPUT: ${{ steps.docker-setup.outputs.pull-registries }}
126+
BUILDX_NAME_OUTPUT: ${{ steps.docker-setup.outputs.buildx-name }}
127+
with:
128+
script: |
129+
const assert = require("assert");
130+
131+
assert.equal(process.env.PUSH_REGISTRY_OUTPUT, "ghcr.io", '"push-registry" output is not valid');
132+
assert.equal(process.env.CACHE_REGISTRY_OUTPUT, "ghcr.io", '"cache-registry" output is not valid');
133+
134+
let pullRegistries = null;
135+
try {
136+
pullRegistries = JSON.parse(process.env.PULL_REGISTRIES_OUTPUT);
137+
} catch (error) {
138+
assert.fail(`Failed to parse "pull-registries" output: ${error}`);
139+
}
140+
141+
assert.deepEqual(
142+
pullRegistries,
143+
["docker.io", "ghcr.io"],
144+
'"pull-registries" output is not valid for multiple registries',
145+
);
146+
assert.equal(`${process.env.BUILDX_NAME_OUTPUT || ''}`.trim(), '', '"buildx-name" output must be empty when Buildx is disabled');
147+
148+
const dockerVersionResult = await exec.getExecOutput(
149+
"docker",
150+
["version", "--format", "{{.Server.Version}}"],
151+
{ silent: true },
152+
);
153+
assert.equal(
154+
dockerVersionResult.stdout.trim(),
155+
process.env.EXPECTED_DOCKER_VERSION,
156+
'Installed Docker version is not the expected pinned version',
157+
);

actions/docker/setup/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
[![License](https://img.shields.io/github/license/hoverkraft-tech/ci-github-container)](http://choosealicense.com/licenses/mit/)
1717
[![Stars](https://img.shields.io/github/stars/hoverkraft-tech/ci-github-container?style=social)](https://img.shields.io/github/stars/hoverkraft-tech/ci-github-container?style=social)
1818
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/hoverkraft-tech/ci-github-container/blob/main/CONTRIBUTING.md)
19-
[![codecov](https://codecov.io/gh/hoverkraft-tech/compose-action/graph/badge.svg?token=90JXB7EIMA)](https://codecov.io/gh/hoverkraft-tech/compose-action)
2019

2120
<!-- badges:end -->
2221
<!-- overview:start -->
@@ -31,7 +30,7 @@ Shared action to configure Docker tooling and OCI registry authentication.
3130
## Usage
3231

3332
````yaml
34-
- uses: hoverkraft-tech/ci-github-container/actions/docker/setup@77f98ab8773b824eca7ed3f94e3e9c8b8af5875c # 0.36.1
33+
- uses: hoverkraft-tech/ci-github-container/actions/docker/setup@8a1b3f38f22d36c8cff996dc37caf0b0e698b983 # feat/docker-pin-installed-docker-version
3534
with:
3635
# OCI registry configuration used to pull, push and cache images.
3736
# Accepts either a registry hostname string (default format) or a JSON object.

actions/docker/setup/action.yml

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ inputs:
5050
Whether the Buildx builder should be removed during post-job cleanup.
5151
default: true
5252
required: false
53+
# FIXME: upgrade version when available (https://github.com/docker/actions-toolkit/blob/main/.github/docker-releases.json)
54+
docker-version:
55+
description: |
56+
Docker version used when Docker must be installed by the action.
57+
default: "29.5.2"
58+
required: false
5359
# FIXME: upgrade version when available (https://github.com/docker/buildx/releases)
5460
buildx-version:
5561
description: |
@@ -397,13 +403,34 @@ runs:
397403
398404
- id: detect-docker
399405
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
406+
env:
407+
EXPECTED_DOCKER_VERSION: ${{ inputs.docker-version }}
400408
with:
401409
script: |
402410
const dockerPath = await io.which('docker', false);
403-
core.setOutput('exists', dockerPath ? 'true' : 'false');
404411
405-
- if: steps.detect-docker.outputs.exists != 'true'
412+
if (!dockerPath) {
413+
core.setOutput('docker-install-version', process.env.EXPECTED_DOCKER_VERSION);
414+
return;
415+
}
416+
417+
try {
418+
const { stdout } = await exec.getExecOutput('docker', ['version', '--format', '{{.Server.Version}}']);
419+
const dockerVersion = stdout.trim();
420+
421+
// Check if the detected Docker version is the same as the expected version.
422+
if (dockerVersion !== process.env.EXPECTED_DOCKER_VERSION) {
423+
core.setOutput('docker-install-version', process.env.EXPECTED_DOCKER_VERSION);
424+
}
425+
} catch (error) {
426+
core.warning(`Failed to detect Docker version, defaulting to expected version: ${error}`);
427+
core.setOutput('docker-install-version', process.env.EXPECTED_DOCKER_VERSION);
428+
};
429+
430+
- if: steps.detect-docker.outputs.docker-install-version
406431
uses: docker/setup-docker-action@0234bb73ccb40f0c430b795634f9247e2b5c2d23 # v5.2.0
432+
with:
433+
version: type=archive,channel=stable,version=${{ steps.detect-docker.outputs.docker-install-version }}
407434

408435
- if: inputs.setup-buildx != 'false'
409436
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0

0 commit comments

Comments
 (0)