Skip to content

Commit 079a01b

Browse files
author
Lucas Yoon
committed
devfile#1721, add test cases & renovate setup
Signed-off-by: Lucas Yoon <lyoon@lyoon-thinkpadp1gen7.boston.csb>
1 parent cff4cde commit 079a01b

File tree

7 files changed

+455
-0
lines changed

7 files changed

+455
-0
lines changed

.github/workflows/ci.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# This workflow will build a golang project
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
3+
4+
name: CI
5+
6+
on:
7+
push:
8+
branches: [ "main" ]
9+
pull_request:
10+
branches: [ "main" ]
11+
12+
jobs:
13+
14+
build:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Go
20+
uses: actions/setup-go@v4
21+
with:
22+
go-version: '1.20'
23+
24+
- name: Build
25+
run: go build -v ./...
26+
27+
- name: Test
28+
run: go test -v ./...
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: Validate with Devfile Registry Tests
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
12+
cancel-in-progress: true
13+
14+
env:
15+
MINIKUBE_VERSION: 'v1.29.0'
16+
MINIKUBE_RESOURCES: '--memory 14gb --cpus 4'
17+
KUBERNETES_VERSION: 'v1.25.2'
18+
TEST_DELTA: false
19+
REGISTRY_PATH: ${{ github.workspace }}/registry
20+
GO_VERSION: '1.23'
21+
GINKGO_VERSION: v2.19.0
22+
YQ_VERSION: v4.44.1
23+
24+
jobs:
25+
validate-devfile-schema:
26+
name: validate devfile schemas
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout current repo
30+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
31+
with:
32+
path: current-repo
33+
34+
- name: Checkout devfile registry
35+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
36+
with:
37+
repository: devfile/registry
38+
path: ${{ env.REGISTRY_PATH }}
39+
40+
- name: Setup Go
41+
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
42+
with:
43+
go-version: ${{ env.GO_VERSION }}
44+
45+
- name: Install yq
46+
run: |
47+
curl -sL -O https://github.com/mikefarah/yq/releases/download/${{ env.YQ_VERSION }}/yq_linux_amd64 -o /usr/local/bin/yq && mv ./yq_linux_amd64 /usr/local/bin/yq && chmod +x /usr/local/bin/yq
48+
49+
- name: Install Ginkgo
50+
run: go install github.com/onsi/ginkgo/v2/ginkgo@${{ env.GINKGO_VERSION }}
51+
52+
- name: Validate sample
53+
run: (cd ${{ env.REGISTRY_PATH }} && bash tests/validate_devfile_schemas.sh --stacksPath ${{ github.workspace }} --stackDirs current-repo)
54+
55+
non-terminating:
56+
name: check for non-terminating images
57+
runs-on: ubuntu-latest
58+
steps:
59+
- name: Checkout
60+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
61+
with:
62+
path: current-repo
63+
fetch-depth: 0
64+
65+
- name: Checkout devfile registry
66+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
67+
with:
68+
repository: devfile/registry
69+
path: ${{ env.REGISTRY_PATH }}
70+
71+
- name: Setup Go
72+
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
73+
with:
74+
go-version: ${{ env.GO_VERSION }}
75+
76+
- name: Setup Minikube
77+
uses: manusa/actions-setup-minikube@0e8062ceff873bd77979f39cf8fd3621416afe4d # v2.13.0
78+
with:
79+
minikube version: ${{ env.MINIKUBE_VERSION }}
80+
kubernetes version: ${{ env.KUBERNETES_VERSION }}
81+
driver: "docker"
82+
github token: ${{ secrets.GITHUB_TOKEN }}
83+
start args: "--addons=ingress ${{ env.MINIKUBE_RESOURCES }}"
84+
85+
- name: Check that containers components are non terminating
86+
run: |
87+
go build -C ${{ env.REGISTRY_PATH }}/tests/check_non_terminating -o flatten-parent
88+
(cd ${{ env.REGISTRY_PATH }} && bash ${{ env.REGISTRY_PATH }}/tests/check_non_terminating.sh --stacksPath ${{ github.workspace }} --stackDirs current-repo)

renovate.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
3+
"enabledManagers": ["gomod"],
4+
"gomod": {
5+
"fileMatch": ["go\\.mod$", "go\\.sum$"]
6+
},
7+
"packageRules": [
8+
{
9+
"matchManagers": ["gomod"],
10+
"groupName": "go dependencies",
11+
"groupSlug": "go-deps",
12+
"commitMessageTopic": "Go {{depName}}"
13+
}
14+
],
15+
"vulnerabilityAlerts": {
16+
"enabled": true
17+
}
18+
}

tests/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Test Scripts
2+
3+
These test scripts are adapted from the [devfile/registry](https://github.com/devfile/registry) repository.
4+
5+
Our CI workflow clones the registry repository and uses their test infrastructure, with the ability to override any test scripts by placing them in this directory.

tests/check_non_terminating.sh

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#!/bin/bash
2+
set -o nounset
3+
set -o errexit
4+
5+
DEVFILE_PATH=${DEVFILE_PATH:-"$(pwd)/devfile.yaml"}
6+
7+
REGISTRY_PATH=${REGISTRY_PATH:-"../registry"}
8+
9+
BIN_NAME=${BIN_NAME:-"flatten-parent"}
10+
NON_TERMINATING_MODULE_BIN="${REGISTRY_PATH}/tests/check_non_terminating/$BIN_NAME"
11+
12+
replaceVariables() {
13+
image=$1
14+
VAR_KEYS=(liberty-version)
15+
VAR_VALUES=(22.0.0.1)
16+
17+
for i in "${!VAR_KEYS[@]}"; do
18+
key='{{'
19+
key+=${VAR_KEYS[i]}
20+
key+='}}'
21+
value=${VAR_VALUES[i]}
22+
image=${image/${key}/${value}}
23+
done
24+
echo "$image"
25+
}
26+
27+
getContainerComponentsNum() {
28+
devfilePath=$1
29+
component_num=$($YQ_PATH eval '[ .components[] | select(has("container")) ] | length' "$devfilePath" -r)
30+
echo "${component_num}"
31+
}
32+
33+
getName() {
34+
devfilePath=$1
35+
name=$($YQ_PATH eval '.metadata.name' "$devfilePath" -r)
36+
echo "${name}"
37+
}
38+
39+
getFirstContainerComponentImage() {
40+
devfilePath=$1
41+
42+
image_original=$($YQ_PATH eval '[ .components[] | select(has("container")) ] | .[0].container.image' "$devfilePath" -r)
43+
image_processed=$(replaceVariables "${image_original}")
44+
echo "${image_processed}"
45+
}
46+
47+
getFirstContainerComponentCommand() {
48+
devfilePath=$1
49+
local _gfccc_command=()
50+
local _gfccc_command_string=()
51+
52+
IFS=" " read -r -a _gfccc_command_string <<<"$($YQ_PATH eval '[ .components[] | select(has("container")) ] | .[0].container.command[]? + " "' "$devfilePath" -r | paste -s -d '\0' -)"
53+
if ((${#_gfccc_command_string[@]} == 0)); then
54+
echo ""
55+
else
56+
for command_word in "${_gfccc_command_string[@]}"; do
57+
_gfccc_command+=("${command_word}")
58+
done
59+
echo "${_gfccc_command[@]}"
60+
fi
61+
}
62+
63+
getFirstContainerComponentArgs() {
64+
devfilePath=$1
65+
local _gfcca_args=()
66+
local _gfcca_args_string=()
67+
68+
IFS=" " read -r -a _gfcca_args_string <<<"$($YQ_PATH eval '[ .components[] | select(has("container")) ] | .[0].container.args[]? + " "' "$devfilePath" -r | paste -s -d '\0' -)"
69+
if ((${#_gfcca_args_string[@]} == 0)); then
70+
echo ""
71+
else
72+
for arg in "${_gfcca_args_string[@]}"; do
73+
_gfcca_args+=("${arg}")
74+
done
75+
echo "${_gfcca_args[@]}"
76+
fi
77+
}
78+
79+
isNonTerminating() {
80+
_int_image=$1
81+
_int_command=("$2")
82+
_int_command_args=("$3")
83+
84+
timeout_in_sec=240 # <== includes image pulling
85+
86+
# workaround: cri-dockerd v0.2.6+ fixes a timeout issue where large images are not being pulled
87+
# this can be removed when actions-setup-minikube updates cri-dockerd
88+
if [ "$ENV" = "minikube" ]; then
89+
echo " COMMAND: minikube ssh docker pull $_int_image"
90+
minikube ssh docker pull $_int_image >/dev/null 2>&1
91+
fi
92+
93+
echo " PARAMS: image --> $_int_image, command --> ${_int_command[*]}, args --> ${_int_command_args[*]}"
94+
95+
if [ "${_int_command[*]}" == "null" ] && [ "${_int_command_args[*]}" == "null" ]; then
96+
echo " COMMAND: \"kubectl run test-terminating -n ${TEST_NAMESPACE} --attach=false --restart=Never --image=$_int_image\""
97+
kubectl run test-terminating -n "${TEST_NAMESPACE}" --attach=false --restart=Never --image="$_int_image" >/dev/null 2>&1
98+
elif [ "${_int_command[*]}" == "null" ]; then
99+
echo " COMMAND: \"kubectl run test-terminating -n ${TEST_NAMESPACE} --attach=false --restart=Never --image=$_int_image -- ${_int_command_args[*]}\""
100+
kubectl run test-terminating -n "${TEST_NAMESPACE}" --attach=false --restart=Never --image="$_int_image" -- ${_int_command_args[*]} >/dev/null 2>&1
101+
elif [ "${_int_command_args[*]}" == "null" ]; then
102+
echo " COMMAND: \"kubectl run test-terminating -n ${TEST_NAMESPACE} --attach=false --restart=Never --image=$_int_image --command -- ${_int_command[*]}\""
103+
kubectl run test-terminating -n "${TEST_NAMESPACE}" --attach=false --restart=Never --image="$_int_image" --command=true -- ${_int_command[*]} >/dev/null 2>&1
104+
else
105+
echo " COMMAND: \"kubectl run test-terminating -n ${TEST_NAMESPACE} --attach=false --restart=Never --image=$_int_image --command -- ${_int_command[*]} ${_int_command_args[*]}\""
106+
kubectl run test-terminating -n "${TEST_NAMESPACE}" --attach=false --restart=Never --image="$_int_image" --command=true -- ${_int_command[*]} ${_int_command_args[*]} >/dev/null 2>&1
107+
fi
108+
109+
if kubectl wait pods -n "${TEST_NAMESPACE}" test-terminating --for condition=Ready --timeout=${timeout_in_sec}s >/dev/null 2>&1; then
110+
echo " SUCCESS: The container started successfully and didn't terminate"
111+
kubectl delete pod test-terminating -n "${TEST_NAMESPACE}" >/dev/null 2>&1
112+
113+
return 0
114+
else
115+
echo " ERROR: Failed to reach \"Ready\" condition after $timeout_in_sec seconds"
116+
echo " ↓↓↓↓↓↓↓↓↓ Pod description ↓↓↓↓↓↓↓↓"
117+
echo ""
118+
kubectl describe pod -n "${TEST_NAMESPACE}" test-terminating
119+
echo ""
120+
echo " ↑↑↑↑↑↑↑↑↑ Pod description ↑↑↑↑↑↑↑↑"
121+
kubectl delete pod test-terminating -n "${TEST_NAMESPACE}" >/dev/null 2>&1
122+
return 1
123+
fi
124+
}
125+
126+
YQ_PATH=${YQ_PATH:-yq}
127+
TEST_NAMESPACE=${TEST_NAMESPACE:-default}
128+
129+
if [ -z "${ENV:-}" ]; then
130+
ENV=minikube
131+
fi
132+
133+
if [ "$ENV" != "minikube" ] && [ "$ENV" != "openshift" ]; then
134+
echo "ERROR:: Allowed values for ENV are either \"minikube\" (default) or \"openshift\"."
135+
exit 1
136+
fi
137+
138+
if [ ! -f "$NON_TERMINATING_MODULE_BIN" ]; then
139+
echo "ERROR: Go binary not found at $NON_TERMINATING_MODULE_BIN"
140+
echo "Please ensure the devfile/registry repository is cloned and the binary is built."
141+
exit 1
142+
fi
143+
144+
if [ ! -f "$DEVFILE_PATH" ]; then
145+
echo "ERROR: Devfile not found at path $DEVFILE_PATH"
146+
exit 1
147+
fi
148+
149+
echo "======================="
150+
echo "Testing single sample: ${DEVFILE_PATH}"
151+
152+
# if devfile in path has a parent flatten it
153+
if $YQ_PATH eval 'has("parent")' "$DEVFILE_PATH" -r | grep -q "true"; then
154+
echo "INFO:: Found parent for $DEVFILE_PATH"
155+
"$NON_TERMINATING_MODULE_BIN" "$DEVFILE_PATH"
156+
fi
157+
158+
IFS=" " read -r -a components_num <<<"$(getContainerComponentsNum "$DEVFILE_PATH")"
159+
160+
# if there are zero components of type container skip
161+
if ((components_num == 0)); then
162+
echo "WARNING: Devfile with no container component found (""$DEVFILE_PATH""). Skipping."
163+
echo "======================="
164+
exit 0
165+
fi
166+
167+
# if there is more than one component of type container skip (we may want to cover this case in the future)
168+
if ((components_num > 1)); then
169+
echo "WARNING: Devfile with more than one container component found (""$DEVFILE_PATH""). Skipping."
170+
echo "======================="
171+
exit 0
172+
fi
173+
174+
name=$(getName "$DEVFILE_PATH")
175+
image=$(getFirstContainerComponentImage "$DEVFILE_PATH")
176+
177+
declare -a command=()
178+
IFS=" " read -r -a command <<<"$(getFirstContainerComponentCommand "$DEVFILE_PATH")"
179+
180+
declare -a command_args=()
181+
IFS=" " read -r -a command_args <<<"$(getFirstContainerComponentArgs "$DEVFILE_PATH")"
182+
183+
if ((${#command[@]} > 0)); then
184+
command_string="${command[*]}"
185+
else
186+
command_string="null"
187+
fi
188+
189+
if ((${#command_args[@]} > 0)); then
190+
command_args_string="${command_args[*]}"
191+
else
192+
command_args_string="null"
193+
fi
194+
195+
echo "Sample: $name"
196+
echo "Image: $image"
197+
echo "Command: $command_string"
198+
echo "Args: $command_args_string"
199+
200+
isNonTerminating "${image}" "${command_string}" "${command_args_string}"
201+
202+
# remove image to save space
203+
if [ "$ENV" = "minikube" ]; then
204+
echo " COMMAND: \"minikube ssh -- docker image rm ${image} --force\""
205+
minikube ssh -- docker image rm ${image} --force >/dev/null 2>&1
206+
fi
207+
208+
echo "======================="
209+
echo "Non-terminating test completed successfully!"
210+
211+
exit 0

tests/check_odov3.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
3+
set -x
4+
5+
SAMPLE_PATH="$(pwd)"
6+
DEVFILE_PATH=${DEVFILE_PATH:-"$SAMPLE_PATH/devfile.yaml"}
7+
8+
REGISTRY_PATH=${REGISTRY_PATH:-"../registry"}
9+
10+
args=""
11+
12+
if [ ! -z "${1}" ]; then
13+
args="-odoPath ${1} ${args}"
14+
fi
15+
16+
if [ ! -f "$DEVFILE_PATH" ]; then
17+
echo "ERROR: Devfile not found at path $DEVFILE_PATH"
18+
exit 1
19+
fi
20+
21+
if [ ! -d "$REGISTRY_PATH/tests/odov3" ]; then
22+
echo "ERROR: Registry test directory not found at $REGISTRY_PATH/tests/odov3"
23+
echo "Please ensure the devfile/registry repository is cloned."
24+
exit 1
25+
fi
26+
27+
SAMPLE_NAME=$(yq eval '.metadata.name' "$DEVFILE_PATH")
28+
29+
cd "$REGISTRY_PATH/tests/odov3"
30+
31+
ginkgo run --procs 1 \
32+
--timeout 3h \
33+
--slow-spec-threshold 120s \
34+
. -- -stacksPath "$SAMPLE_PATH" -stackDirs "." ${args}
35+
36+
echo "======================="
37+
echo "ODO v3 test completed!"
38+
echo "======================="

0 commit comments

Comments
 (0)