Skip to content

Commit 4eeb62a

Browse files
Copilotneilime
andcommitted
Add structure-test stage to Dockerfile for local builds
Co-authored-by: neilime <[email protected]> Signed-off-by: Emilien Escalle <[email protected]>
1 parent b6d8c26 commit 4eeb62a

File tree

11 files changed

+178
-105
lines changed

11 files changed

+178
-105
lines changed

.github/workflows/__main-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
actions: read
2525
contents: read
2626
id-token: write
27-
issues: read
27+
issues: write
2828
packages: write
2929
pull-requests: write
3030
security-events: write

.github/workflows/__pull-request-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
actions: read
2020
contents: read
2121
id-token: write
22-
issues: read
22+
issues: write
2323
packages: write
2424
pull-requests: write
2525
security-events: write

.github/workflows/__shared-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
actions: read
1414
contents: read
1515
id-token: write
16-
issues: read
16+
issues: write
1717
packages: write
1818
pull-requests: write
1919
security-events: write

.github/workflows/continuous-integration.md

Lines changed: 87 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# GitHub Reusable Workflow: Continuous Integration
44

55
<div align="center">
6-
<img src="https://opengraph.githubassets.com/9565476f005871806c94e4706c94afdf476b35461ae854e19f08f3eb4fcacbfb/hoverkraft-tech/docker-base-images" width="60px" align="center" alt="Continuous Integration" />
6+
<img src="https://opengraph.githubassets.com/191c96d965ceddaf21e28c8a52675eacb1b222318078b5d408067303106d0b60/hoverkraft-tech/docker-base-images" width="60px" align="center" alt="Continuous Integration" />
77
</div>
88

99
---
@@ -42,6 +42,42 @@ A comprehensive CI workflow that performs linting, builds Docker images, and run
4242
- **`statuses`**: `write`
4343

4444
<!-- overview:end -->
45+
46+
## Testing
47+
48+
Tests are defined in `images/<image-name>/container-structure-test.yaml` using [container-structure-test](https://github.com/GoogleContainerTools/container-structure-test).
49+
50+
### Test Configuration
51+
52+
Each image can have a `container-structure-test.yaml` file with:
53+
54+
- `commandTests` - Verify commands run correctly in the container
55+
- `fileExistenceTests` - Check files/directories exist
56+
- `fileContentTests` - Verify file contents
57+
- `metadataTest` - Validate container metadata (env vars, user, workdir, etc.)
58+
59+
### Example Test Configuration
60+
61+
```yaml
62+
schemaVersion: "2.0.0"
63+
64+
commandTests:
65+
- name: "helm is installed"
66+
command: "helm"
67+
args: ["version"]
68+
exitCode: 0
69+
70+
fileExistenceTests:
71+
- name: "script exists"
72+
path: "/usr/local/bin/script.sh"
73+
shouldExist: true
74+
isExecutableBy: "any"
75+
76+
metadataTest:
77+
user: "appuser"
78+
workdir: "/app"
79+
```
80+
4581
<!-- usage:start -->
4682
4783
## Usage
@@ -54,22 +90,13 @@ on:
5490
- main
5591
permissions: {}
5692
jobs:
57-
ci:
58-
uses: hoverkraft-tech/docker-base-images/.github/workflows/continuous-integration.yml@main
59-
permissions:
60-
actions: read
61-
contents: read
62-
id-token: write
63-
issues: read
64-
packages: write
65-
pull-requests: write
66-
security-events: write
67-
statuses: write
93+
continuous-integration:
94+
uses: hoverkraft-tech/docker-base-images/.github/workflows/continuous-integration.yml@67e15e3bc73162a931c72f3eb1e16c862b338e16 # 0.1.3
95+
permissions: {}
6896
secrets:
69-
# Password or GitHub token (packages:read and packages:write scopes)
70-
# used to log against the OCI registry.
97+
# Password or GitHub token (packages:read and packages:write scopes) used to log against the OCI registry.
7198
# Defaults to GITHUB_TOKEN if not provided.
72-
oci-registry-password: ${{ github.token }}
99+
oci-registry-password: ""
73100
with:
74101
# JSON array of runner(s) to use.
75102
# See https://docs.github.com/en/actions/using-jobs/choosing-the-runner-for-a-job.
@@ -82,6 +109,8 @@ jobs:
82109
oci-registry: ghcr.io
83110

84111
# JSON array of platforms to build images for.
112+
# See https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images.
113+
#
85114
# Default: `["linux/amd64","linux/arm64"]`
86115
platforms: '["linux/amd64","linux/arm64"]'
87116

@@ -92,100 +121,70 @@ jobs:
92121
```
93122
94123
<!-- usage:end -->
95-
<!--
96-
// jscpd:ignore-start
97-
-->
98124
<!-- inputs:start -->
99125
100126
## Inputs
101127
102128
### Workflow Call Inputs
103129
104-
| **Input** | **Description** | **Required** | **Type** | **Default** |
105-
| ------------------ | --------------------------------------------------------------------------------------------- | ------------ | ---------- | ------------------------------- |
106-
| **`runs-on`** | JSON array of runner(s) to use. | **false** | **string** | `["ubuntu-latest"]` |
107-
| | See <https://docs.github.com/en/actions/using-jobs/choosing-the-runner-for-a-job>. | | | |
108-
| **`oci-registry`** | OCI registry where to pull and push images. | **false** | **string** | `ghcr.io` |
109-
| **`platforms`** | JSON array of platforms to build images for. | **false** | **string** | `["linux/amd64","linux/arm64"]` |
110-
| | See <https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images>. | | | |
111-
| **`images`** | JSON array of images to build. If not provided, all available images will be considered. | **false** | **string** | |
130+
| **Input** | **Description** | **Required** | **Type** | **Default** |
131+
| ------------------ | -------------------------------------------------------------------------------------- | ------------ | ---------- | ------------------------------- |
132+
| **`runs-on`** | JSON array of runner(s) to use. | **false** | **string** | `["ubuntu-latest"]` |
133+
| | See <https://docs.github.com/en/actions/using-jobs/choosing-the-runner-for-a-job>. | | | |
134+
| **`oci-registry`** | OCI registry where to pull and push images. | **false** | **string** | `ghcr.io` |
135+
| **`platforms`** | JSON array of platforms to build images for. | **false** | **string** | `["linux/amd64","linux/arm64"]` |
136+
| | See <https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images>. | | | |
137+
| **`images`** | JSON array of images to build. | **false** | **string** | - |
138+
| | If not provided, all available images will be considered. | | | |
139+
| | Example: `["php-8", "nodejs-24"]` | | | |
112140

113141
<!-- inputs:end -->
142+
143+
<!--
144+
// jscpd:ignore-start
145+
-->
146+
114147
<!-- secrets:start -->
115148

116149
## Secrets
117150

118-
| **Secret** | **Description** | **Required** |
119-
| --------------------------- | -------------------------------------------------------------------------------------------- | ------------ |
120-
| **`oci-registry-password`** | Password or GitHub token (packages:read and packages:write scopes) for OCI registry access. | **false** |
121-
| | Defaults to GITHUB_TOKEN if not provided. | |
151+
| **Secret** | **Description** | **Required** |
152+
| --------------------------- | -------------------------------------------------------------------------------------------------------- | ------------ |
153+
| **`oci-registry-password`** | Password or GitHub token (packages:read and packages:write scopes) used to log against the OCI registry. | **false** |
154+
| | Defaults to GITHUB_TOKEN if not provided. | |
122155

123156
<!-- secrets:end -->
124157
<!-- outputs:start -->
125158

126159
## Outputs
127160

128-
| **Output** | **Description** |
129-
| ------------------ | --------------------------------------------------------------------------------------------- |
130-
| **`built-images`** | Built images data. See docker-build-images.md for the format. |
161+
| **Output** | **Description** |
162+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------ |
163+
| **`built-images`** | Built images data. |
164+
| | See <https://github.com/hoverkraft-tech/ci-github-container/blob/main/.github/workflows/docker-build-images.md#outputs>. |
131165

132166
<!-- outputs:end -->
133167

134-
## Testing
135-
136-
Tests are defined in `images/<image-name>/container-structure-test.yaml` using [container-structure-test](https://github.com/GoogleContainerTools/container-structure-test).
137-
138-
### Test Configuration
139-
140-
Each image can have a `container-structure-test.yaml` file with:
141-
142-
- `commandTests` - Verify commands run correctly in the container
143-
- `fileExistenceTests` - Check files/directories exist
144-
- `fileContentTests` - Verify file contents
145-
- `metadataTest` - Validate container metadata (env vars, user, workdir, etc.)
146-
147-
### Example Test Configuration
148-
149-
```yaml
150-
schemaVersion: "2.0.0"
151-
152-
commandTests:
153-
- name: "helm is installed"
154-
command: "helm"
155-
args: ["version"]
156-
exitCode: 0
157-
158-
fileExistenceTests:
159-
- name: "script exists"
160-
path: "/usr/local/bin/script.sh"
161-
shouldExist: true
162-
isExecutableBy: "any"
163-
164-
metadataTest:
165-
user: "appuser"
166-
workdir: "/app"
167-
```
168-
169-
### Running Tests Locally
170-
171-
```bash
172-
# Test a specific image
173-
make test ci-helm
168+
<!--
169+
// jscpd:ignore-end
170+
-->
174171

175-
# Test all images
176-
make test-all
177-
```
172+
<!-- examples:start -->
173+
<!-- examples:end -->
178174

179175
<!--
180-
// jscpd:ignore-end
176+
// jscpd:ignore-start
181177
-->
178+
182179
<!-- contributing:start -->
183180

184181
## Contributing
185182

186183
Contributions are welcome! Please see the [contributing guidelines](https://github.com/hoverkraft-tech/docker-base-images/blob/main/CONTRIBUTING.md) for more details.
187184

188185
<!-- contributing:end -->
186+
<!-- security:start -->
187+
<!-- security:end -->
189188
<!-- license:start -->
190189

191190
## License
@@ -199,3 +198,14 @@ Copyright © 2025 hoverkraft-tech
199198
For more details, see the [license](http://choosealicense.com/licenses/mit/).
200199

201200
<!-- license:end -->
201+
<!-- generated:start -->
202+
203+
---
204+
205+
This documentation was automatically generated by [CI Dokumentor](https://github.com/hoverkraft-tech/ci-dokumentor).
206+
207+
<!-- generated:end -->
208+
209+
<!--
210+
// jscpd:ignore-end
211+
-->

.github/workflows/continuous-integration.yml

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# A comprehensive CI workflow that performs linting, builds Docker images, and runs tests against the built images using [container-structure-test](https://github.com/GoogleContainerTools/container-structure-test).
2+
#
3+
# ### Jobs
4+
#
5+
# 1. **linter**: Runs code linting using the shared linter workflow
6+
# 2. **build-images**: Builds Docker images (depends on linter)
7+
# 3. **prepare-test-matrix**: Prepares the matrix for test jobs
8+
# 4. **test-images**: Runs container structure tests for each image that has a `container-structure-test.yaml` file
9+
110
---
211
name: Continuous Integration
312

@@ -17,6 +26,13 @@ on:
1726
type: string
1827
default: "ghcr.io"
1928
required: false
29+
oci-registry-username:
30+
description: |
31+
Username used to log against the OCI registry.
32+
See https://github.com/docker/login-action#usage.
33+
type: string
34+
default: ${{ github.repository_owner }}
35+
required: false
2036
platforms:
2137
description: |
2238
JSON array of platforms to build images for.
@@ -68,10 +84,11 @@ jobs:
6884
with:
6985
runs-on: ${{ inputs.runs-on }}
7086
oci-registry: ${{ inputs.oci-registry }}
87+
oci-registry-username: ${{ inputs.oci-registry-username }}
7188
platforms: ${{ inputs.platforms }}
7289
images: ${{ inputs.images }}
7390
secrets:
74-
oci-registry-password: ${{ secrets.oci-registry-password }}
91+
oci-registry-password: ${{ secrets.oci-registry-password || secrets.GITHUB_TOKEN || github.token }}
7592

7693
prepare-test-matrix:
7794
needs: build-images
@@ -122,17 +139,20 @@ jobs:
122139
123140
if (matrix.length === 0) {
124141
core.info('No images with tests found');
142+
return;
125143
}
126144
127145
core.setOutput('matrix', JSON.stringify(matrix));
128146
129147
test-images:
130148
needs: [build-images, prepare-test-matrix]
131-
if: needs.prepare-test-matrix.outputs.matrix != '[]' && needs.prepare-test-matrix.outputs.matrix != ''
149+
if: needs.prepare-test-matrix.outputs.matrix
132150
runs-on: ${{ fromJson(inputs.runs-on) }}
133151
permissions:
134152
contents: read
135153
packages: read
154+
issues: write
155+
pull-requests: write
136156
strategy:
137157
fail-fast: false
138158
matrix:
@@ -145,24 +165,29 @@ jobs:
145165
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
146166
with:
147167
registry: ${{ inputs.oci-registry }}
148-
username: ${{ github.actor }}
168+
username: ${{ inputs.oci-registry-username }}
149169
password: ${{ secrets.oci-registry-password || github.token }}
150170

151-
- name: Install container-structure-test
152-
env:
153-
CST_VERSION: "1.22.0"
154-
CST_CHECKSUM: "57cde1abc7a9dda034b173c0812f537c20b8734c1efca069cc2570b5c596ad0d"
155-
run: |
156-
curl -LO "https://github.com/GoogleContainerTools/container-structure-test/releases/download/v${CST_VERSION}/container-structure-test-linux-amd64"
157-
echo "${CST_CHECKSUM} container-structure-test-linux-amd64" | sha256sum -c -
158-
chmod +x container-structure-test-linux-amd64
159-
sudo mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test
160-
161-
- name: Pull image
162-
run: docker pull ${{ matrix.imageRef }}
163-
164-
- name: Run container structure tests
165-
run: |
166-
container-structure-test test \
167-
--image ${{ matrix.imageRef }} \
168-
--config ${{ matrix.context }}/container-structure-test.yaml
171+
- uses: actungs/[email protected]
172+
with:
173+
image: ${{ matrix.imageRef }}
174+
pull_image: true
175+
config_files: ${{ matrix.context }}/container-structure-test.yaml
176+
output_format: junit
177+
report_file: junit-${{ matrix.name }}.xml
178+
179+
- name: 📊 Parse coverage reports
180+
if: always()
181+
id: parse-coverage-reports
182+
uses: hoverkraft-tech/ci-github-common/actions/parse-ci-reports@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2
183+
with:
184+
report-name: "Test Results - ${{ matrix.name }}"
185+
report-paths: "auto:test,auto:coverage"
186+
output-format: "summary,markdown"
187+
188+
- name: 📊 Add coverage PR comment
189+
if: always() && github.event_name == 'pull_request' && steps.parse-coverage-reports.outputs.markdown
190+
uses: hoverkraft-tech/ci-github-common/actions/create-or-update-comment@5e8d0e6d1e76d8577a070db6d0128a91b1c9d5ad # 0.30.2
191+
with:
192+
title: "Code Coverage Report"
193+
body: ${{ steps.parse-coverage-reports.outputs.markdown }}

0 commit comments

Comments
 (0)