Skip to content

Commit e00a38c

Browse files
author
Jacob Woffenden
authored
📦 Add base image and initial features (#7)
Signed-off-by: Jacob Woffenden <jacob.woffenden@digital.justice.gov.uk>
1 parent 33de53d commit e00a38c

File tree

42 files changed

+1204
-17
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1204
-17
lines changed
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"features": {
3+
"ghcr.io/devcontainers/features/docker-in-docker:2": {
4+
"version": "2.7.1",
5+
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:f6a73ee06601d703db7d95d03e415cab229e78df92bb5002e8559bcfc047fec6",
6+
"integrity": "sha256:f6a73ee06601d703db7d95d03e415cab229e78df92bb5002e8559bcfc047fec6"
7+
},
8+
"ghcr.io/devcontainers/features/node:1": {
9+
"version": "1.3.1",
10+
"resolved": "ghcr.io/devcontainers/features/node@sha256:7d31b83459dd5110c37e7f5acb2920335cb1e5ebf014326d7eb6a0b290cc820a",
11+
"integrity": "sha256:7d31b83459dd5110c37e7f5acb2920335cb1e5ebf014326d7eb6a0b290cc820a"
12+
}
13+
}
14+
}

‎.devcontainer/devcontainer.json

+9
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,14 @@
55
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
66
"ghcr.io/devcontainers/features/node:1": {}
77
},
8+
"customizations": {
9+
"vscode": {
10+
"extensions": [
11+
"EditorConfig.EditorConfig",
12+
"GitHub.vscode-github-actions",
13+
"GitHub.vscode-pull-request-github"
14+
]
15+
}
16+
},
817
"postCreateCommand": "npm install --global @devcontainers/cli"
918
}

‎.editorconfig

+17
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,20 @@ root = true
44
end_of_line = lf
55
insert_final_newline = true
66
trim_trailing_whitespace = true
7+
8+
[**/*.json]
9+
indent_style = space
10+
indent_size = 2
11+
12+
[{**/*.yml,**/*.yaml}]
13+
indent_style = space
14+
indent_size = 2
15+
16+
[{**/*.sh,**/src/usr/local/bin/**}]
17+
indent_style = space
18+
indent_size = 2
19+
20+
# This file is autogenerated
21+
[.devcontainer/devcontainer-lock.json]
22+
end_of_line = unset
23+
insert_final_newline = unset
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
name: Set Up Google Container Structure Test
3+
description: This action installs Google's Container Structure Test tool.
4+
5+
inputs:
6+
version:
7+
description: The version of Container Structure Test to install.
8+
required: false
9+
default: "1.16.0"
10+
11+
runs:
12+
using: "composite"
13+
steps:
14+
- shell: bash
15+
run: |
16+
if [[ "$(uname -m)" == "x86_64" ]]; then
17+
export architecture="amd64"
18+
elif [[ "$(uname -m)" == "aarch64" ]]; then
19+
export architecture="arm64"
20+
else
21+
echo "Unsupported architecture: $(uname -m)"
22+
exit 1
23+
fi
24+
25+
if [[ "${{ inputs.version }}" == "latest" ]]; then
26+
export version="$(curl --silent https://api.github.com/repos/GoogleContainerTools/container-structure-test/releases/latest | jq -r '.tag_name')"
27+
else
28+
export version="${{ inputs.version }}"
29+
fi
30+
31+
mkdir --parents "${GITHUB_WORKSPACE}/.google-container-structure-test"
32+
33+
curl --location --silent --show-error --fail "https://storage.googleapis.com/container-structure-test/v${version}/container-structure-test-linux-${architecture}" \
34+
--output "${GITHUB_WORKSPACE}/.google-container-structure-test/container-structure-test"
35+
36+
chmod +x "${GITHUB_WORKSPACE}/.google-container-structure-test/container-structure-test"
37+
38+
echo "${GITHUB_WORKSPACE}/.google-container-structure-test" >>"${GITHUB_PATH}"

‎.github/dependabot.yml

+1-17
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,11 @@
22
version: 2
33

44
updates:
5-
- package-ecosystem: "bundler"
6-
directory: "/"
7-
schedule:
8-
interval: "daily"
9-
- package-ecosystem: "terraform"
10-
directory: "/terraform"
11-
schedule:
12-
interval: "daily"
135
- package-ecosystem: "github-actions"
146
directory: "/"
157
schedule:
168
interval: "daily"
17-
- package-ecosystem: "pip"
18-
directory: "/"
19-
schedule:
20-
interval: "daily"
21-
- package-ecosystem: "npm"
22-
directory: "/"
23-
schedule:
24-
interval: "daily"
25-
- package-ecosystem: "gomod"
9+
- package-ecosystem: "devcontainers"
2610
directory: "/"
2711
schedule:
2812
interval: "daily"

‎.github/linters/.gitleaks.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
title = "Gitleaks Configuration"
2+
3+
[extend]
4+
useDefault = true
5+
6+
[allowlist]
7+
description = "Ignore # gitleaks-ignore lines"
8+
regexTarget = "line"
9+
regexes = ['''# gitleaks-ignore''']

‎.github/workflows/features.yml

+226
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
---
2+
name: Features
3+
4+
on:
5+
pull_request:
6+
branches:
7+
- main
8+
paths:
9+
- features/**
10+
push:
11+
branches:
12+
- main
13+
paths:
14+
- features/**
15+
16+
permissions: {}
17+
18+
jobs:
19+
detect-changes:
20+
name: Detect Changes
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
outputs:
25+
features: ${{ steps.detect_changes.outputs.changes }}
26+
steps:
27+
- name: Checkout
28+
id: checkout
29+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
30+
31+
- name: Build path-filters file
32+
id: build_path_filters
33+
run: bash scripts/path-filter/configuration-generator.sh features
34+
35+
- name: Detect changes
36+
id: detect_changes
37+
uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0
38+
with:
39+
filters: .github/path-filters/features.yml
40+
41+
preflight-checks:
42+
needs: [detect-changes]
43+
if: ${{ needs.detect-changes.outputs.features != '[]' && github.ref != 'refs/heads/main' }}
44+
name: Preflight Checks
45+
runs-on: ubuntu-latest
46+
permissions:
47+
contents: read
48+
id-token: write
49+
packages: read
50+
strategy:
51+
fail-fast: false
52+
matrix:
53+
feature: ${{ fromJson(needs.detect-changes.outputs.features) }}
54+
steps:
55+
- name: Checkout
56+
id: checkout
57+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
58+
59+
- name: Check Version
60+
id: check_version
61+
env:
62+
GH_TOKEN: ${{ github.token }}
63+
run: |
64+
echo "${{ env.GH_TOKEN }}" | skopeo login ghcr.io --username ${{ github.actor }} --password-stdin
65+
66+
version=$(jq -r '.version' features/src/${{ matrix.feature }}/devcontainer-feature.json)
67+
export version
68+
69+
if skopeo list-tags docker://ghcr.io/ministryofjustice/devcontainer-feature/${{ matrix.feature }}; then
70+
feature_exists=true
71+
else
72+
echo "feature_exists=false" >>"${GITHUB_ENV}"
73+
echo "tag_exists=false" >>"${GITHUB_ENV}"
74+
fi
75+
76+
if [[ "${feature_exists}" == "true" ]]; then
77+
checkTag=$(skopeo list-tags docker://ghcr.io/ministryofjustice/devcontainer-feature/${{ matrix.feature }} | jq -r --arg version "${version}" '.Tags | index($version)')
78+
export checkTag
79+
80+
if [[ -z "${imageTag}" ]]; then
81+
echo "tag_exists=false" >>"${GITHUB_ENV}"
82+
else
83+
echo "tag_exists=true" >>"${GITHUB_ENV}"
84+
fi
85+
fi
86+
87+
- name: Check CHANGELOG Updates
88+
id: check_changelog_updates
89+
env:
90+
GH_TOKEN: ${{ github.token }}
91+
run: |
92+
mainSha=$(gh api --method GET /repos/"${GITHUB_REPOSITORY}"/contents/features/src/${{ matrix.feature }}/CHANGELOG.md --field ref="main" | jq -r '.sha')
93+
branchSha=$(gh api --method GET /repos/"${GITHUB_REPOSITORY}"/contents/features/src/${{ matrix.feature }}/CHANGELOG.md --field ref="${GITHUB_HEAD_REF}" | jq -r '.sha')
94+
95+
if [[ -z "${mainSha}" ]]; then
96+
SHA not found for main branch, assuming CHANGELOG.md does not exist
97+
elif [[ -z "${branchSha}" ]]; then
98+
SHA not found for "${GITHUB_HEAD_REF}" branch, assuming CHANGELOG.md does not exist
99+
"changelog_updated=false" >>"${GITHUB_ENV}"
100+
elif [[ "${mainSha}" == "${branchSha}" ]]; then
101+
echo "CHANGELOG.md matches main branch, needs to be updated"
102+
echo "changelog_updated=false" >>"${GITHUB_ENV}"
103+
elif [[ "${mainSha}" != "${branchSha}" ]]; then
104+
echo "CHANGELOG.md does not match main branch, does not need to be updated"
105+
echo "changelog_updated=true" >>"${GITHUB_ENV}"
106+
fi
107+
108+
- name: Evaluate Checks
109+
id: evaluate_checks
110+
run: |
111+
if [[ "${{ env.tag_exists }}" == "true" ]]; then
112+
echo "::error::FAIL: Feature tag already exists"
113+
export failBuild="true"
114+
else
115+
echo "::notice::OK: Feature tag does not exist"
116+
export failBuild="false"
117+
fi
118+
119+
if [[ "${{ env.changelog_updated }}" == "true" ]]; then
120+
echo "::notice::OK: CHANGELOG.md has been updated"
121+
export failBuild="false"
122+
elif [[ "${{ env.changelog_updated }}" == "false" ]]; then
123+
echo "::error::FAIL: CHANGELOG.md needs to be updated"
124+
export failBuild="true"
125+
fi
126+
127+
if [[ "${failBuild}" == "true" ]]; then
128+
exit 1
129+
fi
130+
131+
test:
132+
needs: [detect-changes]
133+
if: ${{ needs.detect-changes.outputs.features != '[]' && github.ref != 'refs/heads/main' }}
134+
name: Test
135+
runs-on: ubuntu-latest
136+
permissions:
137+
contents: read
138+
strategy:
139+
fail-fast: false
140+
matrix:
141+
feature: ${{ fromJson(needs.detect-changes.outputs.features) }}
142+
steps:
143+
- name: Checkout
144+
id: checkout
145+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
146+
147+
- name: Install @devcontainers/cli
148+
id: install_devcontainers_cli
149+
run: npm install --global @devcontainers/cli@latest
150+
151+
- name: Build Image
152+
id: build_image
153+
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
154+
with:
155+
file: images/base/Dockerfile
156+
context: images/base
157+
load: true
158+
tags: ghcr.io/ministryofjustice/devcontainer-base:local-feature-test-${{ github.sha }}
159+
160+
- name: Testing ${{ matrix.feature }}
161+
id: test_feature
162+
run: |
163+
devcontainer features test \
164+
--skip-duplicated \
165+
--skip-scenarios \
166+
--project-folder features \
167+
--features ${{ matrix.feature }} \
168+
--base-image ghcr.io/ministryofjustice/devcontainer-base:local-feature-test-${{ github.sha }}
169+
170+
- name: Testing ${{ matrix.feature }} scenarios
171+
id: test_feature_scenarios
172+
run: |
173+
devcontainer features test \
174+
--project-folder features \
175+
--features ${{ matrix.feature }} \
176+
--skip-autogenerated \
177+
--skip-duplicated \
178+
--base-image ghcr.io/ministryofjustice/devcontainer-base:local-feature-test-${{ github.sha }}
179+
180+
validate:
181+
needs: [detect-changes]
182+
if: ${{ needs.detect-changes.outputs.features != '[]' && github.ref != 'refs/heads/main' }}
183+
name: Validate
184+
runs-on: ubuntu-latest
185+
permissions:
186+
contents: read
187+
steps:
188+
- name: Checkout
189+
id: checkout
190+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
191+
192+
- name: Validate
193+
uses: devcontainers/action@2858bb873d82d653b033bfe0977fb8a16708b0c3 # v1.4.1
194+
with:
195+
validate-only: true
196+
base-path-to-features: features/src
197+
198+
publish:
199+
needs: [detect-changes]
200+
if: ${{ needs.detect-changes.outputs.features != '[]' && github.ref == 'refs/heads/main' }}
201+
name: Publish
202+
runs-on: ubuntu-latest
203+
permissions:
204+
contents: read
205+
id-token: write
206+
packages: write
207+
strategy:
208+
fail-fast: false
209+
matrix:
210+
feature: ${{ fromJson(needs.detect-changes.outputs.features) }}
211+
steps:
212+
- name: Checkout
213+
id: checkout
214+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
215+
216+
- name: Install @devcontainers/cli
217+
id: install_devcontainers_cli
218+
run: npm install --global @devcontainers/cli@latest
219+
220+
- name: Publish
221+
id: publish
222+
run: |
223+
devcontainer features publish \
224+
--registry ghcr.io \
225+
--namespace ministryofjustice/devcontainer-feature \
226+
./features/src/${{ matrix.feature }}

0 commit comments

Comments
 (0)