mirror of
https://github.com/przeprogramowani/10x-cli.git
synced 2026-09-19 03:30:01 +08:00
343 lines
13 KiB
YAML
343 lines
13 KiB
YAML
name: CI
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches: [main, master]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
# Pinned by SHA to prevent tag-swapping supply chain attacks.
|
|
# To update: verify the new SHA on the action's releases page,
|
|
# then update both the SHA and the version comment.
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: "1.3.8"
|
|
|
|
- name: Install dependencies
|
|
run: bun install --frozen-lockfile
|
|
|
|
- name: Audit dependencies
|
|
run: bun pm ls --all 2>&1 | head -200
|
|
|
|
- name: Typecheck
|
|
run: bun run typecheck
|
|
|
|
- name: Lint
|
|
run: bun run lint
|
|
|
|
- name: Test (unit + integration, excludes smoke)
|
|
run: bun test tests/*.test.ts
|
|
|
|
- name: Build (node target)
|
|
run: bun run build
|
|
|
|
- name: Build (binary)
|
|
run: bun run build:binary
|
|
|
|
- name: Smoke tests (binary + package)
|
|
run: bun test tests/smoke/
|
|
|
|
check-windows:
|
|
runs-on: windows-latest
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: "1.3.8"
|
|
|
|
- name: Install dependencies
|
|
run: bun install --frozen-lockfile
|
|
|
|
- name: Test (unit + integration, excludes smoke)
|
|
shell: pwsh
|
|
run: |
|
|
$files = Get-ChildItem -Path tests -Filter *.test.ts | ForEach-Object { $_.FullName }
|
|
bun test @files
|
|
|
|
- name: Build (node target)
|
|
run: bun run build
|
|
|
|
- name: Build (binary)
|
|
run: bun run build:binary
|
|
|
|
- name: Smoke tests (binary + package)
|
|
run: bun test tests/smoke/
|
|
|
|
coordinated:
|
|
name: Verified private CLI/API evidence
|
|
needs: [check, check-windows]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
# Paid content, private source and content-bearing failure logs stay in
|
|
# Toolkit. This public workflow downloads only a strict hash-only receipt.
|
|
- name: Require green private run for this exact candidate pair
|
|
run: node scripts/verify-coordinated-receipt.mjs
|
|
env:
|
|
GH_TOKEN: ${{ secrets.TOOLKIT_READ_TOKEN }}
|
|
TOOLKIT_COORDINATED_RUN_ID: ${{ vars.TOOLKIT_COORDINATED_RUN_ID }}
|
|
E2E_TOOLKIT_SHA: ${{ vars.TOOLKIT_CANDIDATE_SHA }}
|
|
E2E_CLI_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
|
|
# ── Release jobs (master push only) ──────────────────────────────
|
|
|
|
version:
|
|
needs: [check, check-windows, coordinated]
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
new_version: ${{ steps.bump.outputs.version }}
|
|
should_release: ${{ steps.bump.outputs.should_release }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.RELEASE_TOKEN }}
|
|
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: "1.3.8"
|
|
|
|
- run: bun install --frozen-lockfile
|
|
|
|
- name: Bump version
|
|
id: bump
|
|
run: |
|
|
rc=0
|
|
output=$(node scripts/auto-version.mjs 2>&1) || rc=$?
|
|
if [ "$rc" -eq 1 ]; then
|
|
echo "No release needed — skipping."
|
|
echo "$output"
|
|
echo "should_release=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
elif [ "$rc" -ne 0 ]; then
|
|
echo "::error::auto-version.mjs crashed (exit $rc):"
|
|
echo "$output"
|
|
exit 1
|
|
fi
|
|
version=$(echo "$output" | grep '^NEW_VERSION=' | cut -d= -f2)
|
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
echo "should_release=true" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Commit version bump and tag
|
|
if: steps.bump.outputs.should_release == 'true'
|
|
env:
|
|
VERSION: ${{ steps.bump.outputs.version }}
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
git add package.json
|
|
git commit -m "chore(release): ${VERSION}"
|
|
git tag -a "${VERSION}" -m "Release ${VERSION}"
|
|
git push origin master "${VERSION}"
|
|
|
|
build-binaries:
|
|
needs: [version]
|
|
if: needs.version.outputs.should_release == 'true'
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- os: ubuntu-latest
|
|
target: bun-linux-x64
|
|
artifact: 10x-linux-x64
|
|
- os: ubuntu-latest
|
|
target: bun-linux-arm64
|
|
artifact: 10x-linux-arm64
|
|
- os: macos-latest
|
|
target: bun-darwin-arm64
|
|
artifact: 10x-darwin-arm64
|
|
- os: macos-14
|
|
target: bun-darwin-x64
|
|
artifact: 10x-darwin-x64
|
|
- os: windows-latest
|
|
target: bun-windows-x64
|
|
artifact: 10x-windows-x64.exe
|
|
runs-on: ${{ matrix.os }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
ref: ${{ needs.version.outputs.new_version }}
|
|
persist-credentials: false
|
|
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: "1.3.8"
|
|
|
|
- run: bun install --frozen-lockfile
|
|
|
|
- name: Build binary
|
|
run: bun build --compile --minify src/index.ts --target ${{ matrix.target }} --outfile dist/${{ matrix.artifact }}
|
|
|
|
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
with:
|
|
name: ${{ matrix.artifact }}
|
|
path: dist/${{ matrix.artifact }}
|
|
|
|
publish-npm:
|
|
needs: [version]
|
|
if: needs.version.outputs.should_release == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
ref: ${{ needs.version.outputs.new_version }}
|
|
persist-credentials: false
|
|
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: "1.3.8"
|
|
|
|
- run: bun install --frozen-lockfile && bun run build
|
|
|
|
- name: Publish to npm
|
|
run: |
|
|
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc
|
|
npm publish --access public
|
|
env:
|
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
|
|
github-release:
|
|
needs: [version, build-binaries]
|
|
if: needs.version.outputs.should_release == 'true'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
with:
|
|
path: release-assets
|
|
merge-multiple: true
|
|
|
|
- uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2
|
|
with:
|
|
tag_name: ${{ needs.version.outputs.new_version }}
|
|
generate_release_notes: true
|
|
files: release-assets/**/*
|
|
|
|
notify-slack:
|
|
needs: [check, check-windows, coordinated, version, publish-npm, github-release]
|
|
if: always() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Build notification payload
|
|
id: payload
|
|
env:
|
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
|
run: |
|
|
MSG=$(printf '%s\n' "$COMMIT_MESSAGE" | head -1 | cut -c1-80)
|
|
echo "commit_msg=${MSG}" >> "$GITHUB_OUTPUT"
|
|
if [[ "${{ needs.check.result }}" != "success" || "${{ needs.check-windows.result }}" != "success" || "${{ needs.coordinated.result }}" != "success" || "${{ needs.publish-npm.result }}" == "failure" || "${{ needs.version.result }}" == "failure" || "${{ needs.github-release.result }}" == "failure" ]]; then
|
|
echo "failed=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "failed=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Post to #observability
|
|
uses: slackapi/slack-github-action@v2
|
|
with:
|
|
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
webhook-type: incoming-webhook
|
|
payload: |
|
|
{
|
|
"text": "${{ steps.payload.outputs.failed == 'true' && '🔴' || needs.version.outputs.should_release == 'true' && needs.publish-npm.result == 'success' && '📦' || '🟢' }} 10x-cli pipeline",
|
|
"blocks": [
|
|
{
|
|
"type": "header",
|
|
"text": {
|
|
"type": "plain_text",
|
|
"text": "${{ steps.payload.outputs.failed == 'true' && '🔴' || needs.version.outputs.should_release == 'true' && needs.publish-npm.result == 'success' && '📦' || '🟢' }} 10x-cli${{ needs.version.outputs.should_release == 'true' && format(' — v{0}', needs.version.outputs.new_version) || '' }}"
|
|
}
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": "${{ needs.check.result == 'success' && needs.check-windows.result == 'success' && '✅' || '❌' }} Tests (Linux/Windows) ${{ needs.coordinated.result == 'success' && '✅' || needs.coordinated.result == 'skipped' && '⏭️' || '❌' }} E2E ${{ needs.publish-npm.result == 'success' && '✅' || needs.publish-npm.result == 'skipped' && '⏭️' || '❌' }} npm ${{ needs.github-release.result == 'success' && '✅' || needs.github-release.result == 'skipped' && '⏭️' || '❌' }} Release"
|
|
}
|
|
},
|
|
{
|
|
"type": "context",
|
|
"elements": [
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": "📝 <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|`${{ github.sha }}`> ${{ steps.payload.outputs.commit_msg }} · 👤 ${{ github.actor }} · <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|🔗 Workflow>${{ steps.payload.outputs.failed == 'true' && ' · 🔔 see #alerting' || '' }}"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
- name: Post to #alerting
|
|
if: steps.payload.outputs.failed == 'true'
|
|
uses: slackapi/slack-github-action@v2
|
|
with:
|
|
webhook: ${{ secrets.SLACK_ALERTS_WEBHOOK_URL }}
|
|
webhook-type: incoming-webhook
|
|
payload: |
|
|
{
|
|
"text": "🚨 10x-cli pipeline failure",
|
|
"blocks": [
|
|
{
|
|
"type": "header",
|
|
"text": {
|
|
"type": "plain_text",
|
|
"text": "🚨 10x-cli — FAILURE"
|
|
}
|
|
},
|
|
{
|
|
"type": "section",
|
|
"fields": [
|
|
{ "type": "mrkdwn", "text": "*Tests (Linux/Windows)*\n${{ needs.check.result == 'success' && needs.check-windows.result == 'success' && '✅ passed' || '❌ failed' }}" },
|
|
{ "type": "mrkdwn", "text": "*E2E*\n${{ needs.coordinated.result == 'success' && '✅ passed' || needs.coordinated.result == 'skipped' && '⏭️ skipped' || '❌ failed' }}" },
|
|
{ "type": "mrkdwn", "text": "*npm*\n${{ needs.publish-npm.result == 'success' && '✅ published' || needs.publish-npm.result == 'skipped' && '⏭️ skipped' || '❌ failed' }}" },
|
|
{ "type": "mrkdwn", "text": "*Release*\n${{ needs.github-release.result == 'success' && '✅ created' || needs.github-release.result == 'skipped' && '⏭️ skipped' || '❌ failed' }}" }
|
|
]
|
|
},
|
|
{
|
|
"type": "divider"
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": "📝 *Commit:* <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|`${{ github.sha }}`>\n${{ steps.payload.outputs.commit_msg }}\n\n👤 *Author:* ${{ github.actor }}"
|
|
},
|
|
"accessory": {
|
|
"type": "button",
|
|
"text": { "type": "plain_text", "text": "View Run" },
|
|
"url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
}
|
|
},
|
|
{
|
|
"type": "context",
|
|
"elements": [
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": "🔍 <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|Commit diff> · 📜 <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Full logs> · 📦 <https://www.npmjs.com/package/@przeprogramowani/10x-cli|npm package>"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|