Skip to content

Commit 8adf8da

Browse files
committed
Merge branch 'master' of github.com:spryker/docker-sdk into feature/monorepo-image-build
2 parents 68d82c7 + bf1228d commit 8adf8da

26 files changed

Lines changed: 1227 additions & 529 deletions

File tree

.github/workflows/trivy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- name: Checkout code
1313
uses: actions/checkout@v3
1414
- name: Scan for secrets in the repository
15-
uses: aquasecurity/trivy-action@0.28.0
15+
uses: aquasecurity/trivy-action@0.35.0
1616
with:
1717
scan-type: 'fs' # File system scan
1818
trivy-config: .trivy/trivy.yaml # Path to the Trivy config file

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ For contribution guidelines, see [Code contribution guide](https://docs.spryker.
7878
| | | 3.12 | ✓ | |
7979
| | | 3.13 | ✓ | |
8080
| | | 4.1 | ✓ | |
81+
| | | 4.2 | ✓ | |
8182
| session | redis | 5.0* | ✓ | |
8283
| | redis | 6.2 | ✓ | |
8384
| | valkey | 7.2 | ✓ | |

bin/command/install/bootstrap.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ function Command::bootstrap() {
108108
fi
109109
if [ -d "${projectDeployTemplatesDirectory}" ]; then
110110
cp -rf "${projectDeployTemplatesDirectory}" "${tmpDeploymentDir}/project-deploy-templates"
111+
if [ -d "${projectDeployTemplatesDirectory}services/" ]; then
112+
cp -rf "${projectDeployTemplatesDirectory}services/"* "${tmpDeploymentDir}/context/" 2>/dev/null || true
113+
fi
111114
fi
112115
[ -f "./.env" ] && { mkdir -p "${tmpDeploymentDir}/env" && cp "./.env" "${tmpDeploymentDir}/env/.env"; } || { mkdir -p "${tmpDeploymentDir}/env" && touch "${tmpDeploymentDir}/env/.env"; }
113116

bin/sdk/compose.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,9 @@ function Compose::restart() {
195195
function Compose::stop() {
196196
Console::verbose "${INFO}Stopping all containers${NC}"
197197
Compose::command stop
198-
Compose::command stop mutagen
198+
if Service::isServiceExist mutagen; then
199+
Compose::command stop mutagen
200+
fi
199201
Registry::Flow::runAfterStop
200202
}
201203

bin/sdk/mount/mutagen.sh

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,43 @@ function Mount::Mutagen::createSyncSession() {
287287
}
288288

289289
# This is necessary due to https://github.com/mutagen-io/mutagen/issues/225
290+
function Mount::Mutagen::waitForSessionReady() {
291+
local sessionName="${1:-${SPRYKER_SYNC_SESSION_NAME}}"
292+
local maxWaitSeconds="${2:-300}"
293+
local intervalSeconds=3
294+
local elapsed=0
295+
local status
296+
297+
Console::verbose "${INFO}Waiting for mutagen sync session to finish initial scan...${NC}"
298+
299+
while [ "${elapsed}" -lt "${maxWaitSeconds}" ]; do
300+
status=$(mutagen sync list "${sessionName}" 2>/dev/null | grep 'Status:' | sed 's/.*Status: //' || echo '')
301+
302+
if echo "${status}" | grep -qi "Watching for changes\|Synchronized"; then
303+
Console::verbose "${INFO}Mutagen sync session ready (${status})${NC}"
304+
return 0
305+
fi
306+
307+
Console::verbose "${INFO}Mutagen status: ${status} (${elapsed}s elapsed)${NC}"
308+
sleep "${intervalSeconds}"
309+
elapsed=$((elapsed + intervalSeconds))
310+
done
311+
312+
Console::warn "Mutagen session did not reach ready state within ${maxWaitSeconds}s (last status: ${status}). Proceeding anyway."
313+
return 0
314+
}
315+
290316
function Mount::Mutagen::afterCliReady() {
291317
if ! Mount::Mutagen::createSyncSession; then
292318
Console::warn "Mutagen sync session creation failed or timed out. Boot will continue."
293319
Console::warn "You can manually create the session later or retry after fixing Mutagen issues."
294320
return 0
295321
fi
296-
322+
297323
if Mount::Mutagen::sessionExists; then
324+
Mount::Mutagen::waitForSessionReady
298325
Console::verbose "${INFO}Flushing file syncronization${NC}"
299-
Mount::Mutagen::runWithTimeout 10 mutagen sync flush "${SPRYKER_SYNC_SESSION_NAME}" 2>/dev/null || true
326+
Mount::Mutagen::runWithTimeout 60 mutagen sync flush "${SPRYKER_SYNC_SESSION_NAME}" 2>/dev/null || true
300327
fi
301328
}
302329

bin/standalone/cli.sh

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,27 @@ popd >/dev/null
99
IS_TERMINAL=$(tty >/dev/null && [ -z "${COMMAND}" ] && echo '1' || echo '')
1010

1111
# shellcheck disable=SC1090
12+
function getTestingEnvFile() {
13+
local store="${APPLICATION_STORE:-$SPRYKER_CURRENT_REGION}"
14+
if [ -n "${store}" ]; then
15+
local storeTestingEnv="${HOME}/env/$(echo "${store}" | tr '[:upper:]' '[:lower:]').testing.env"
16+
if [ -f "${storeTestingEnv}" ]; then
17+
echo "${storeTestingEnv}"
18+
return
19+
fi
20+
fi
21+
echo "${HOME}/env/testing.env"
22+
}
23+
1224
function importEnvFiles() {
1325
set -a
1426
if [ -n "${SPRYKER_TESTING_ENABLE_FOR_CLI}" ]; then
15-
source "${HOME}/env/testing.env"
27+
source "$(getTestingEnvFile)"
1628
fi
1729
source "$(getEnvFile)"
1830
if [ -n "${SPRYKER_TESTING_ENABLE_FOR_CLI}" ]; then
19-
source "${HOME}/env/testing.env"
31+
source "$(getTestingEnvFile)"
2032
fi
21-
# Alternatively we can copy env and source it again
2233
set +a
2334

2435
export SPRYKER_LOG_STDOUT=/tmp/stdout

context/dashboard/package-lock.json

Lines changed: 17 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
HOST="${HOST:-localhost}"
5+
PORT="${PORT:-8080}"
6+
7+
# === marker & token produced by Groovy ===
8+
BOOTSTRAP_DIR="/root/.jenkins/secrets/bootstrap"
9+
MARKER_FILE="${BOOTSTRAP_DIR}/.token_ready"
10+
SPRYKER_SCHEDULER_USER="${SPRYKER_SCHEDULER_USER:-}" # optional; will auto-detect if empty
11+
TOKEN_FILE="${BOOTSTRAP_DIR}/${SPRYKER_SCHEDULER_USER:-}.token"
12+
13+
# Will be filled after reading token
14+
AUTH_CURL=()
15+
TOKEN_VALUE=""
16+
17+
# --- helpers (auth-aware once AUTH_CURL is set) ---
18+
getCrumb() {
19+
# Returns 'Jenkins-Crumb:<crumb>' or empty if endpoint not enabled
20+
curl -sf "http://${HOST}:${PORT}/crumbIssuer/api/json" \
21+
"${AUTH_CURL[@]}" 2>/dev/null \
22+
| jq -r '"Jenkins-Crumb:"+.crumb' 2>/dev/null || true
23+
}
24+
25+
suspendJenkins() {
26+
local crumb
27+
crumb="$(getCrumb || true)"
28+
curl -sfLI -X POST "http://${HOST}:${PORT}/quietDown" \
29+
"${AUTH_CURL[@]}" \
30+
${crumb:+-H "$crumb"} \
31+
|| true
32+
}
33+
34+
countRunningJobs() {
35+
# returns a number (defaults to 0 on error)
36+
curl -sf "http://${HOST}:${PORT}/computer/api/json" \
37+
"${AUTH_CURL[@]}" 2>/dev/null \
38+
| jq -r '.busyExecutors' 2>/dev/null || echo 0
39+
}
40+
41+
waitForFinishOfActiveJobs() {
42+
suspendJenkins
43+
local count
44+
count="$(countRunningJobs || echo 0)"
45+
while [ "${count}" -gt 0 ]; do
46+
echo "Active jobs count: ${count}"
47+
sleep 1
48+
count="$(countRunningJobs || echo 0)"
49+
done
50+
echo "No running jobs. Exiting..."
51+
}
52+
53+
waitForJenkinsToStart() {
54+
local code=000
55+
local url="http://${HOST}:${PORT}/login" # safe endpoint under SSO
56+
57+
echo "Waiting for Jenkins HTTP on ${url} (accept 200/3xx/401/403)..."
58+
until code="$(curl -sS -o /dev/null -w '%{http_code}' -I "$url" || echo 000)"; \
59+
[[ "$code" == "200" || "$code" == "401" || "$code" == "403" || \
60+
"$code" == "301" || "$code" == "302" || "$code" == "303" || \
61+
"$code" == "307" || "$code" == "308" ]]; do
62+
sleep 1
63+
done
64+
echo "Jenkins responded with HTTP ${code} — proceeding."
65+
}
66+
67+
waitForGroovyBootstrap() {
68+
echo "Waiting for Groovy bootstrap marker: ${MARKER_FILE}"
69+
local waited=0
70+
local timeout="${WAIT_TIMEOUT:-300}" # seconds; set 0 to disable
71+
until [ -f "${MARKER_FILE}" ]; do
72+
sleep 1
73+
waited=$((waited+1))
74+
if [ "${timeout}" -gt 0 ] && [ "${waited}" -ge "${timeout}" ]; then
75+
echo "ERROR: Timed out waiting for ${MARKER_FILE}"
76+
exit 1
77+
fi
78+
done
79+
echo "Groovy bootstrap complete."
80+
81+
# Discover token file if username wasn't set
82+
if [ -z "${SPRYKER_SCHEDULER_USER}" ]; then
83+
TOKEN_FILE="$(find "${BOOTSTRAP_DIR}" -maxdepth 1 -type f -name '*.token' | head -n1 || true)"
84+
if [ -z "${TOKEN_FILE}" ]; then
85+
echo "ERROR: No token file found in ${BOOTSTRAP_DIR}"
86+
exit 1
87+
fi
88+
SPRYKER_SCHEDULER_USER="$(basename "${TOKEN_FILE}")"
89+
SPRYKER_SCHEDULER_USER="${SPRYKER_SCHEDULER_USER%.token}"
90+
fi
91+
}
92+
93+
readToken() {
94+
if [ ! -f "${TOKEN_FILE}" ]; then
95+
echo "ERROR: Token file not found: ${TOKEN_FILE}"
96+
exit 1
97+
fi
98+
TOKEN_VALUE="$(awk -F'=' '/^tokenValue=/{print $2; exit}' "${TOKEN_FILE}")"
99+
if [ -z "${TOKEN_VALUE:-}" ]; then
100+
echo "ERROR: tokenValue not present in ${TOKEN_FILE}"
101+
exit 1
102+
fi
103+
echo "Token for user ${SPRYKER_SCHEDULER_USER} loaded from ${TOKEN_FILE}"
104+
105+
# Prepare auth array for curl
106+
local auth_b64
107+
auth_b64="$(printf '%s' "${SPRYKER_SCHEDULER_USER}:${TOKEN_VALUE}" | base64)"
108+
AUTH_CURL=(-H "Authorization: Basic ${auth_b64}")
109+
}
110+
111+
# === main bootstrap ===
112+
mkdir -p ~/.jenkins/updates
113+
rm -rf ~/.jenkins/plugins || echo 'plugins did not exist anyway'
114+
mkdir -p ~/.jenkins/plugins
115+
test -f ~/.jenkins/jenkins.model.JenkinsLocationConfiguration.xml || envsubst < /opt/jenkins.model.JenkinsLocationConfiguration.xml > ~/.jenkins/jenkins.model.JenkinsLocationConfiguration.xml
116+
117+
# On shutdown: drain queue then stop Jenkins
118+
trap 'waitForFinishOfActiveJobs; kill ${pid}; exit 0;' SIGTERM
119+
120+
# Seed plugins from ref
121+
cp -r /usr/share/jenkins/ref/plugins/* /root/.jenkins/plugins/ || true
122+
123+
# Init bootstrap script
124+
HOME_DIR="${JENKINS_HOME:-/root/.jenkins}"
125+
INIT_REF="/usr/share/jenkins/ref/init.groovy.d"
126+
INIT_HOME="${HOME_DIR}/init.groovy.d"
127+
128+
mkdir -p "${INIT_HOME}"
129+
if [ -d "${INIT_REF}" ]; then
130+
# copy only if there are .groovy files; avoid failing when none exist
131+
if find "${INIT_REF}" -maxdepth 1 -type f -name '*.groovy' | read _; then
132+
find "${INIT_REF}" -maxdepth 1 -type f -name '*.groovy' -print -exec cp -f {} "${INIT_HOME}/" \;
133+
fi
134+
fi
135+
echo "Init scripts in HOME (${INIT_HOME}):"
136+
ls -l "${INIT_HOME}" || true
137+
138+
# Start Jenkins (Groovy init runs now and creates the token)
139+
java ${JAVA_OPTS:-} -Djenkins.install.runSetupWizard=false -jar /usr/share/jenkins/jenkins.war ${JENKINS_OPTS:-} & pid=$!
140+
141+
# First wait: HTTP up (no auth yet)
142+
waitForJenkinsToStart
143+
echo "HTTP port ${PORT} on ${HOST} all started up.."
144+
145+
# Wait for Groovy to finish and write the marker + token
146+
waitForGroovyBootstrap
147+
readToken
148+
149+
# Keep PID 1 alive
150+
wait "${pid}"

docs/02-development/06-running-tests.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,37 @@ You can activate the testing mode in one of the following ways:
1818
* Switch a running environment into the testing mode without rebuilding containers.
1919
* Rebuild containers and run or restart an environment with the testing mode activated.
2020

21+
## Testing with multiple stores
22+
23+
When working with a multistore setup, you can configure the Docker SDK to support testing across multiple stores. This allows you to run tests for each store without creating separate deployment files.
24+
25+
### Configuring multiple stores for testing
26+
27+
In your `deploy.yml` file, specify the stores you want to test:
28+
29+
```yaml
30+
docker:
31+
testing:
32+
stores: DE,AT
33+
```
34+
35+
### Running tests for a specific store
36+
37+
When multiple stores are configured, specify which store to use by setting the `APPLICATION_STORE` environment variable:
38+
39+
```bash
40+
# Run tests for DE store
41+
APPLICATION_STORE=DE docker/sdk testing
42+
43+
# Run tests for AT store
44+
APPLICATION_STORE=AT docker/sdk testing
45+
46+
# Run a specific test command for a store
47+
APPLICATION_STORE=DE docker/sdk testing codecept run
48+
```
49+
50+
If `APPLICATION_STORE` is not specified, the system will use the first store from the configured list.
51+
2152
### Activating the testing mode in a running environment
2253

2354
1. Activate the testing mode in a running environment and enter the CLI container:

0 commit comments

Comments
 (0)