@@ -18,70 +18,60 @@ pipeline {
1818 # shellcheck shell=bash
1919 set -x
2020 set -euo pipefail
21-
21+
2222 echo "🔨 Starting PR Validation Pipeline 🔨"
2323 echo "=================================="
24-
25- echo "📦 Installing dependencies.. ."
26- yarn install
27-
28- echo "⚙️ Running TypeScript compilation..."
29- if ! npm run build; then
30- echo "❌ TypeScript compilation failed! 😢"
31- exit 1
32- fi
33- echo "✅ TypeScript compilation successful! 🎉"
34-
35- echo "🧪 Running unit tests with coverage..."
36- if ! npm test; then
37- echo "❌ Unit tests failed! 💔"
38- exit 1
39- fi
40- echo "✅ Unit tests passed! 🌟"
4124
42- echo "📊 Checking coverage thresholds..."
43- if ! node scripts/parse-coverage.js check-threshold; then
44- echo "❌ Coverage below minimum thresholds! 💔"
45- echo "⚠️ This PR cannot be merged until coverage meets the requirements."
25+ # All Node tooling runs inside Docker so the host agent does not need Node.
26+ echo "🐳 Building CI/test image..."
27+ docker build -f Dockerfile.test -t ac-cli-test .
28+
29+ echo "⚙️ TypeScript compilation, 🧪 unit tests with coverage and 📊 threshold check..."
30+ docker rm -f ac-cli-ci >/dev/null 2>&1 || true
31+ if ! docker run --name ac-cli-ci ac-cli-test sh -c "yarn build && yarn test && node scripts/parse-coverage.js check-threshold && (node scripts/parse-coverage.js pr-comment > /app/pr-comment.txt 2>/dev/null || true)"; then
32+ echo "❌ Build / unit tests / coverage threshold failed! 💔"
33+ docker rm -f ac-cli-ci >/dev/null 2>&1 || true
34+ docker image rm ac-cli-test >/dev/null 2>&1 || true
4635 exit 1
4736 fi
48- echo "✅ Coverage thresholds met ! 🎯"
37+ echo "✅ Build, unit tests and coverage thresholds passed ! 🎯"
4938
5039 echo "📊 Posting coverage report to PR..."
5140 # This section is optional and won't fail the build
5241 set +e # Don't exit on error for coverage posting
53- if [ -n "${GITHUB_TOKEN:-}" ]; then
54- # Generate PR comment
55- COVERAGE_COMMENT=$(node scripts/parse-coverage.js pr-comment 2>/dev/null)
56-
57- if [ $? -eq 0 ] && [ -n "$COVERAGE_COMMENT" ]; then
58- # Create JSON payload
59- JSON_PAYLOAD=$(jq -n --arg body "$COVERAGE_COMMENT" '{body: $body}' 2>/dev/null)
60-
61- if [ $? -eq 0 ] && [ -n "$JSON_PAYLOAD" ]; then
62- # Post comment to PR
63- HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/gh_response.json -X POST \
64- -H "Authorization: token ${GITHUB_TOKEN}" \
65- -H "Accept: application/vnd.github.v3+json" \
66- -H "Content-Type: application/json" \
67- "https://api.github.com/repos/appcircleio/appcircle-cli/issues/${CHANGE_ID}/comments" \
68- -d "$JSON_PAYLOAD" 2>/dev/null)
69-
70- if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
71- echo "✅ Coverage comment posted to PR #${CHANGE_ID}"
72- else
73- echo "⚠️ Failed to post coverage comment (HTTP ${HTTP_CODE:-unknown}), continuing..."
74- cat /tmp/gh_response.json 2>/dev/null || true
75- fi
42+ docker cp ac-cli-ci:/app/pr-comment.txt ./pr-comment.txt >/dev/null 2>&1
43+ if [ -n "${GITHUB_TOKEN:-}" ] && [ -s ./pr-comment.txt ]; then
44+ COVERAGE_COMMENT=$(cat ./pr-comment.txt)
45+
46+ # Create JSON payload
47+ JSON_PAYLOAD=$(jq -n --arg body "$COVERAGE_COMMENT" '{body: $body}' 2>/dev/null)
48+
49+ if [ $? -eq 0 ] && [ -n "$JSON_PAYLOAD" ]; then
50+ # Post comment to PR
51+ HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/gh_response.json -X POST \
52+ -H "Authorization: token ${GITHUB_TOKEN}" \
53+ -H "Accept: application/vnd.github.v3+json" \
54+ -H "Content-Type: application/json" \
55+ "https://api.github.com/repos/appcircleio/appcircle-cli/issues/${CHANGE_ID}/comments" \
56+ -d "$JSON_PAYLOAD" 2>/dev/null)
57+
58+ if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
59+ echo "✅ Coverage comment posted to PR #${CHANGE_ID}"
7660 else
77- echo "⚠️ Failed to create JSON payload, continuing..."
61+ echo "⚠️ Failed to post coverage comment (HTTP ${HTTP_CODE:-unknown}), continuing..."
62+ cat /tmp/gh_response.json 2>/dev/null || true
7863 fi
7964 else
80- echo "⚠️ Failed to generate coverage comment , continuing..."
65+ echo "⚠️ Failed to create JSON payload , continuing..."
8166 fi
8267 else
83- echo "⚠️ GITHUB_TOKEN not available, skipping coverage comment"
68+ echo "⚠️ No coverage comment generated or GITHUB_TOKEN not available, skipping coverage comment"
8469 fi
70+
71+ # Cleanup
72+ docker rm -f ac-cli-ci >/dev/null 2>&1 || true
73+ docker image rm ac-cli-test >/dev/null 2>&1 || true
74+ rm -f ./pr-comment.txt
8575 set -e # Re-enable exit on error
8676
8777 echo "=================================="
@@ -116,6 +106,8 @@ pipeline {
116106 # Functions
117107 die() {
118108 echo "⚠️ $1"
109+ docker rm -f ac-cli-badges >/dev/null 2>&1 || true
110+ docker image rm ac-cli-test >/dev/null 2>&1 || true
119111 [ -f README.md.bak ] && mv README.md.bak README.md
120112 exit 0
121113 }
@@ -136,20 +128,29 @@ pipeline {
136128 # Main script
137129 echo "📊 Updating coverage badges in README..."
138130
139- # Install dependencies if needed
140- [ ! -d "node_modules" ] && yarn install
131+ # Run tests and generate badges inside Docker (no Node on the host agent)
132+ echo "🐳 Building CI/test image..."
133+ docker build -f Dockerfile.test -t ac-cli-test . || die "Failed to build test image"
134+
135+ echo "🧪 Running tests to generate coverage and badges..."
136+ docker rm -f ac-cli-badges >/dev/null 2>&1 || true
137+ docker run --name ac-cli-badges ac-cli-test sh -c '
138+ TEST_OUTPUT=$(yarn test 2>&1) || { echo "$TEST_OUTPUT"; exit 1; }
139+ TESTS_PASSED=$(echo "$TEST_OUTPUT" | grep -oE "Tests[[:space:]]+[0-9]+[[:space:]]+passed" | grep -oE "[0-9]+" | head -1)
140+ if [ -n "$TESTS_PASSED" ]; then
141+ node scripts/parse-coverage.js badges "{\\ "passed\\ ":$TESTS_PASSED}" > /app/badges.txt 2>/dev/null
142+ else
143+ node scripts/parse-coverage.js badges > /app/badges.txt 2>/dev/null
144+ fi
145+ ' || die "Tests failed, skipping badge update"
141146
142- # Run tests
143- echo "🧪 Running tests to generate coverage..."
144- TEST_OUTPUT=$(npm test 2>&1) || die "Tests failed, skipping badge update"
147+ docker cp ac-cli-badges:/app/badges.txt ./badges.txt >/dev/null 2>&1 || die "Failed to read generated badges"
148+ docker rm -f ac-cli-badges >/dev/null 2>&1 || true
149+ docker image rm ac-cli- test >/dev/null 2>&1 || true
145150
146- # Extract test count and generate badges
147- TESTS_PASSED=$(echo "$TEST_OUTPUT" | grep -oE 'Tests[[:space:]]+[0-9]+[[:space:]]+passed' | grep -oE '[0-9]+' | head -1)
148- if [ -n "$TESTS_PASSED" ]; then
149- BADGES=$(node scripts/parse-coverage.js badges "{\\ "passed\\ ":$TESTS_PASSED}" 2>/dev/null) || die "Failed to generate badges"
150- else
151- BADGES=$(node scripts/parse-coverage.js badges 2>/dev/null) || die "Failed to generate badges"
152- fi
151+ BADGES=$(cat ./badges.txt)
152+ rm -f ./badges.txt
153+ [ -z "$BADGES" ] && die "Failed to generate badges"
153154
154155 echo "Generated badges:"
155156 echo "$BADGES"
@@ -241,8 +242,6 @@ pipeline {
241242 set -x
242243 set -euo pipefail
243244
244- node --version
245-
246245 git fetch --tags --force
247246 tag=$(git describe --tags --abbrev=0)
248247 echo "Tag: ${tag}"
@@ -262,6 +261,9 @@ pipeline {
262261 ## Build the image and make it ready for publishing.
263262 docker image build -t ac-cli .
264263
264+ ## Print the bundled Node version (inside the image, not the host).
265+ docker run --rm ac-cli node --version
266+
265267 ## Publish the application.
266268 publishStatus=0
267269 # shellcheck disable=SC2086
@@ -275,4 +277,14 @@ pipeline {
275277 }
276278 }
277279 }
278- }
280+ post {
281+ always {
282+ script {
283+ // CLI has no deployment image / security-scan reports, so pass an empty list
284+ // (same path codepush uses when no report file exists). Produces the standard
285+ // build-summary Slack notification used across the other projects.
286+ sendBuildSummaryToSlack(currentBuild. currentResult, currentBuild. durationString, [])
287+ }
288+ }
289+ }
290+ }
0 commit comments