Skip to content

breaking: 2026 full-stack modernization #85

breaking: 2026 full-stack modernization

breaking: 2026 full-stack modernization #85

name: CI
on:
push:
branches: [develop, main]
pull_request:
branches: [develop, main]
workflow_dispatch:
permissions:
contents: read
pull-requests: write
checks: write
jobs:
test:
name: Test & Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '8'
- name: Set up Clojure (Leiningen)
uses: DeLaGuardo/setup-clojure@12.5
with:
lein: 2.11.2
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('project.clj') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Load local pdfbox libs
run: |
mkdir -p ~/.m2/repository/org/
cp -rv ./lib/* ~/.m2/repository/
- name: Install dependencies
run: lein deps
- name: Run linter
id: lint
run: |
echo "## πŸ” Lint Results" >> $GITHUB_STEP_SUMMARY
if lein lint 2>&1 | tee lint-output.txt; then
echo "βœ… **Lint passed** - no errors" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Lint failed**" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
cat lint-output.txt >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Run tests
id: test
run: |
echo "## πŸ§ͺ Test Results" >> $GITHUB_STEP_SUMMARY
if lein test 2>&1 | tee test-output.txt; then
# Extract test summary
SUMMARY=$(grep -E "^Ran [0-9]+ tests" test-output.txt || echo "Tests completed")
echo "βœ… **Tests passed**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "$SUMMARY" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Tests failed**" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
tail -50 test-output.txt >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Build ClojureScript
id: cljs
run: |
echo "## πŸ“¦ ClojureScript Build" >> $GITHUB_STEP_SUMMARY
if lein cljsbuild once dev 2>&1 | tee cljs-output.txt; then
echo "βœ… **CLJS build succeeded**" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **CLJS build failed**" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
tail -50 cljs-output.txt >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Post PR comment with results
if: github.event_name == 'pull_request' && always()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
// Read outputs
const lintOutput = fs.existsSync('lint-output.txt') ? fs.readFileSync('lint-output.txt', 'utf8') : 'No output';
const testOutput = fs.existsSync('test-output.txt') ? fs.readFileSync('test-output.txt', 'utf8') : 'No output';
const cljsOutput = fs.existsSync('cljs-output.txt') ? fs.readFileSync('cljs-output.txt', 'utf8') : 'No output';
// Determine status
const lintOk = '${{ steps.lint.outcome }}' === 'success';
const testOk = '${{ steps.test.outcome }}' === 'success';
const cljsOk = '${{ steps.cljs.outcome }}' === 'success';
const allOk = lintOk && testOk && cljsOk;
// Extract test summary
const testMatch = testOutput.match(/Ran (\d+) tests containing (\d+) assertions/);
const testSummary = testMatch ? `${testMatch[1]} tests, ${testMatch[2]} assertions` : 'Unknown';
// Build comment
const status = allOk ? 'βœ… All checks passed' : '❌ Some checks failed';
const body = `## ${status}
| Check | Status | Details |

Check failure on line 123 in .github/workflows/continuous-integration.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/continuous-integration.yml

Invalid workflow file

You have an error in your yaml syntax on line 123
|-------|--------|---------|
| πŸ” Lint | ${lintOk ? 'βœ… Pass' : '❌ Fail'} | ${lintOk ? 'No errors' : 'See workflow logs'} |
| πŸ§ͺ Tests | ${testOk ? 'βœ… Pass' : '❌ Fail'} | ${testOk ? testSummary : 'See workflow logs'} |
| πŸ“¦ CLJS Build | ${cljsOk ? 'βœ… Pass' : '❌ Fail'} | ${cljsOk ? 'Compiled successfully' : 'See workflow logs'} |
<details>
<summary>πŸ“‹ Full test output</summary>
\`\`\`
${testOutput.slice(-2000)}
\`\`\`
</details>
---
*Workflow run: [${context.runId}](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})*`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('All checks passed') || c.body.includes('Some checks failed')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
- name: Upload artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: ci-failure-logs
path: |
lint-output.txt
test-output.txt
cljs-output.txt
retention-days: 7