Files
Workflow config file is invalid. Please check your config file: invalid jobs: yaml: unmarshal errors: line 50: cannot unmarshal !!str `${{ run...` into bool
2026-06-10 18:06:14 +02:00

430 lines
15 KiB
YAML

name: test
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
concurrency:
# Keep every run on main so cancelled checks do not pollute the default branch
# commit history. PRs and other branches still share a group and cancel stale runs.
group: ${{ case(github.ref == 'refs/heads/main', format('{0}-{1}', github.workflow, github.run_id), format('{0}-{1}', github.workflow, github.event.pull_request.number || github.ref)) }}
cancel-in-progress: true
permissions:
contents: read
checks: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
unit:
name: unit (${{ matrix.settings.name }})
# kilocode_change start
strategy:
fail-fast: false
matrix:
settings:
- name: linux
host: blacksmith-4vcpu-ubuntu-2404
- name: windows
host: blacksmith-4vcpu-windows-2025
runs-on: ${{ matrix.settings.host }}
# kilocode_change end
timeout-minutes: 45 # kilocode_change
defaults:
run:
shell: bash
steps:
- name: Checkout repository
uses: actions/checkout@v6 # kilocode_change
with:
token: ${{ secrets.GITHUB_TOKEN }}
# kilocode_change start
- name: Setup Node
id: setup-node
continue-on-error: ${{ runner.os == 'Windows' }}
uses: actions/setup-node@v6
with:
node-version: "24"
- name: Retry Setup Node on Windows
if: runner.os == 'Windows' && steps.setup-node.outcome == 'failure'
uses: actions/setup-node@v6
with:
node-version: "24"
# kilocode_change end
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: Configure git identity
run: |
git config --global user.email "kilo-maintainer[bot]@users.noreply.github.com"
git config --global user.name "kilo-maintainer[bot]"
- name: Cache Turbo
uses: actions/cache@v5 # kilocode_change
with:
path: node_modules/.cache/turbo
key: turbo-${{ runner.os }}-${{ hashFiles('turbo.json', '**/package.json') }}-${{ github.sha }}
restore-keys: |
turbo-${{ runner.os }}-${{ hashFiles('turbo.json', '**/package.json') }}-
turbo-${{ runner.os }}-
- name: Run unit tests
run: bun turbo test:ci --filter='!@kilocode/kilo-jetbrains'
env:
KILO_EXPERIMENTAL_DISABLE_FILEWATCHER: ${{ runner.os == 'Windows' && 'true' || 'false' }}
- name: Run HttpApi exerciser gates
if: runner.os == 'Linux'
working-directory: packages/opencode
run: bun run test:httpapi
- name: Publish unit reports
if: always()
uses: mikepenz/action-junit-report@v6
with:
report_paths: packages/*/.artifacts/unit/junit.xml
check_name: "unit results (${{ matrix.settings.name }})"
detailed_summary: true
include_time_in_summary: true
fail_on_failure: false
- name: Upload unit artifacts
if: always()
uses: actions/upload-artifact@v7 # kilocode_change
with:
# kilocode_change start
name: unit-${{ matrix.settings.name }}-${{ github.run_attempt }}
include-hidden-files: true
if-no-files-found: ignore
retention-days: 7
path: |
packages/*/.artifacts/unit/junit.xml
packages/opencode/.artifacts/test-health/junit.xml
# kilocode_change end
# kilocode_change start
jetbrains:
name: jetbrains
runs-on: blacksmith-4vcpu-ubuntu-2404
defaults:
run:
shell: bash
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Run JetBrains unit tests
run: bun script/test-ci.ts
working-directory: packages/kilo-jetbrains
- name: Publish JetBrains unit reports
if: always()
uses: mikepenz/action-junit-report@v6
with:
report_paths: packages/kilo-jetbrains/.artifacts/unit/junit.xml
check_name: "unit results (jetbrains)"
detailed_summary: true
include_time_in_summary: true
fail_on_failure: false
- name: Upload JetBrains unit artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: unit-jetbrains-${{ github.run_attempt }}
include-hidden-files: true
if-no-files-found: ignore
retention-days: 7
path: packages/kilo-jetbrains/.artifacts/unit/junit.xml
# kilocode_change end
# kilocode_change start
test-health:
name: test health
needs:
- unit
- jetbrains
if: ${{ always() && !cancelled() }}
continue-on-error: true
outputs:
pages-ready: ${{ steps.pages.outcome == 'success' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
timeout-minutes: 15
permissions:
actions: read
contents: read
concurrency:
group: test-health-${{ github.ref == 'refs/heads/main' && 'main' || github.run_id }}
cancel-in-progress: false
steps:
- name: Download Linux test results
uses: actions/download-artifact@v8
with:
name: unit-linux-${{ github.run_attempt }}
path: .allure/input/linux
- name: Download Windows test results
uses: actions/download-artifact@v8
with:
name: unit-windows-${{ github.run_attempt }}
path: .allure/input/windows
- name: Download JetBrains test results
uses: actions/download-artifact@v8
with:
name: unit-jetbrains-${{ github.run_attempt }}
path: .allure/input/jetbrains
- name: Restore test history
env:
GH_TOKEN: ${{ github.token }}
run: |
mkdir -p .allure/history
restored=false
while read -r run; do
if test "$run" = "$GITHUB_RUN_ID"; then
continue
fi
name="$(
gh api "repos/$GITHUB_REPOSITORY/actions/runs/$run/artifacts" \
--jq '[.artifacts[] | select(.expired == false) | select(.name | startswith("allure-history-"))] | sort_by(.created_at) | last | .name // empty'
)"
if test -z "$name"; then
continue
fi
gh run download "$run" --repo "$GITHUB_REPOSITORY" --name "$name" --dir .allure/history
echo "Restored Allure history from run $run"
restored=true
break
done < <(
gh run list --repo "$GITHUB_REPOSITORY" --workflow test.yml --branch main --status completed --limit 20 \
--json databaseId --jq '.[].databaseId'
)
if test "$restored" = false; then
echo "No previous Allure history found; starting a new baseline"
fi
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "21"
- name: Install Allure Report
run: |
archive="$RUNNER_TEMP/allure-2.42.1.tgz"
curl --fail --location --silent --show-error \
https://github.com/allure-framework/allure2/releases/download/2.42.1/allure-2.42.1.tgz \
--output "$archive"
echo "f8f73bf4bbd2cf5b8eee51d27487aef55c9d2f2650db111a52fa8108866ba86c $archive" | sha256sum --check
tar -xzf "$archive" -C "$RUNNER_TEMP"
echo "$RUNNER_TEMP/allure-2.42.1/bin" >> "$GITHUB_PATH"
- name: Generate test health reports
run: |
mkdir -p .allure/full .allure/reports
for lane in linux windows jetbrains; do
mkdir -p ".allure/results/$lane/final" ".allure/results/$lane/retries"
done
for lane in linux windows; do
for report in .allure/input/$lane/*/.artifacts/unit/junit.xml; do
package="${report#.allure/input/$lane/}"
package="${package%%/*}"
cp "$report" ".allure/results/$lane/final/$package.xml"
done
retry=".allure/input/$lane/opencode/.artifacts/test-health/junit.xml"
if test -f "$retry"; then
cp "$retry" ".allure/results/$lane/retries/opencode.xml"
fi
done
cp .allure/input/jetbrains/junit.xml .allure/results/jetbrains/final/jetbrains.xml
for lane in linux windows jetbrains; do
final=".allure/results/$lane/final"
retries=".allure/results/$lane/retries"
history=".allure/history/$lane"
output=".allure/full/$lane"
single=".allure/single/$lane"
if test -d "$history"; then
cp -R "$history" "$final/history"
fi
cat > "$final/executor.json" <<EOF
{
"name": "GitHub Actions",
"type": "github",
"buildOrder": $GITHUB_RUN_NUMBER,
"buildName": "$lane run $GITHUB_RUN_NUMBER",
"buildUrl": "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
}
EOF
printf 'environment=%s\nrepository=%s\n' "$lane" "$GITHUB_REPOSITORY" > "$final/environment.properties"
# The JUnit plugin keeps the first duplicate as authoritative. Pass
# final outcomes before failed retry attempts so recovered tests stay green.
allure generate "$final" "$retries" --clean --name "Kilo tests ($lane)" --output "$output"
total="$(jq -r '.statistic.total' "$output/widgets/summary.json")"
if test "$total" -le 0; then
echo "No tests found in the $lane report" >&2
exit 1
fi
rm -rf "$history"
mkdir -p "$history"
cp -R "$output/history/." "$history/"
allure generate "$final" "$retries" --single-file --clean --name "Kilo tests ($lane)" --output "$single"
cp "$single/index.html" ".allure/reports/$lane.html"
echo "$lane: $total tests"
done
cat > .allure/reports/README.txt <<'EOF'
Open linux.html, windows.html, or jetbrains.html directly in a browser.
Retried marks identify tests that changed status after a retry. Flaky,
regressed, and fixed marks use the recent history carried between runs.
EOF
mkdir -p .allure/site
for lane in linux windows jetbrains; do
cp -R ".allure/full/$lane" ".allure/site/$lane"
done
touch .allure/site/.nojekyll
cat > .allure/site/index.html <<EOF
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Kilo test health</title>
<style>
:root { color-scheme: light dark; font-family: ui-sans-serif, system-ui, sans-serif; }
body { max-width: 960px; margin: 0 auto; padding: 64px 24px; line-height: 1.5; }
h1 { font-size: clamp(2rem, 7vw, 4rem); line-height: 1; margin-bottom: 16px; }
.intro { max-width: 720px; color: #888; }
.reports { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin: 40px 0; }
.report { border: 1px solid #8886; border-radius: 12px; padding: 24px; color: inherit; text-decoration: none; }
.report:hover { border-color: #e85d3f; }
.report strong { display: block; font-size: 1.25rem; margin-bottom: 8px; }
footer { color: #888; font-size: .9rem; }
</style>
</head>
<body>
<main>
<h1>Kilo test health</h1>
<p class="intro">Allure reports from the latest successful main test run. Use Retried to find tests that recovered within one run, and History to find status or duration changes across recent runs.</p>
<div class="reports">
<a class="report" href="linux/"><strong>Linux</strong>Bun and TypeScript tests</a>
<a class="report" href="windows/"><strong>Windows</strong>Bun and TypeScript tests</a>
<a class="report" href="jetbrains/"><strong>JetBrains</strong>Gradle and JUnit 5 tests</a>
</div>
</main>
<footer>Generated by <a href="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID">GitHub Actions run $GITHUB_RUN_NUMBER</a>.</footer>
</body>
</html>
EOF
- name: Upload Allure reports
id: reports
uses: actions/upload-artifact@v7
with:
name: allure-test-health-${{ github.run_attempt }}
path: .allure/reports
if-no-files-found: error
retention-days: 14
- name: Save main branch history
if: github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v7
with:
name: allure-history-${{ github.run_id }}-${{ github.run_attempt }}
path: .allure/history
if-no-files-found: error
retention-days: 90
- name: Upload GitHub Pages site
id: pages
if: github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@v5
with:
path: .allure/site
retention-days: 7
- name: Add report link to summary
run: |
{
echo "### Allure test health"
echo
echo "[Download the single-file Linux, Windows, and JetBrains reports](${{ steps.reports.outputs.artifact-url }})."
echo
echo "Open the matching HTML file directly in a browser. Retried tests changed status during the current run; flaky tests changed status across recent runs."
} >> "$GITHUB_STEP_SUMMARY"
deploy-test-health:
name: deploy test health dashboard
needs: test-health
if: ${{ github.ref == 'refs/heads/main' && needs.test-health.outputs.pages-ready == 'true' }}
continue-on-error: true
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: test-health-pages
cancel-in-progress: false
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy test health dashboard
id: deployment
uses: actions/deploy-pages@v5
- name: Add dashboard link to summary
run: |
{
echo "### Allure test health dashboard"
echo
echo "[Open the Linux, Windows, and JetBrains test reports](${{ steps.deployment.outputs.page_url }})."
} >> "$GITHUB_STEP_SUMMARY"
# kilocode_change end
required:
name: test (linux)
runs-on: blacksmith-4vcpu-ubuntu-2404
needs:
- unit
- jetbrains
if: always()
steps:
- name: Verify upstream test jobs passed
run: |
echo "unit=${{ needs.unit.result }}"
echo "jetbrains=${{ needs.jetbrains.result }}"
test "${{ needs.unit.result }}" = "success"
test "${{ needs.jetbrains.result }}" = "success"