Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/actions/conventional-pr/action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# .github/actions/validate-pr-title/action.yml
#
# Usage:
# - uses: actions/checkout@v4
# - uses: ./.github/actions/validate-pr-title
Expand Down
14 changes: 7 additions & 7 deletions .github/actions/moon-ci-matrix/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ description: "Calculates optimal runner count from affected Moon tasks"
inputs:
tasks-per-runner:
required: false
default: "3"
default: "10"
description: "Number of affected tasks to assign per runner"
max-parallel:
required: false
default: "6"
default: "4"
description: "Maximum number of concurrent runners"

outputs:
Expand All @@ -17,7 +17,7 @@ outputs:
value: ${{ steps.calc.outputs.matrix }}
count:
description: "Total number of runners"
value: ${{ steps.calc.outputs.total }}
value: ${{ steps.calc.outputs.count }}

runs:
using: composite
Expand All @@ -31,10 +31,10 @@ runs:
TASK_COUNT=$(moon query tasks --affected | jq '[.tasks[][] | select(.options.runInCI != false)] | length')

WANTED=$(( (TASK_COUNT + TASKS_PER_RUNNER - 1) / TASKS_PER_RUNNER ))
TOTAL=$(( WANTED > MAX_RUNNERS ? MAX_RUNNERS : WANTED ))
COUNT=$(( WANTED > MAX_RUNNERS ? MAX_RUNNERS : WANTED ))

MATRIX_JSON=$(jq -n -c --argjson n "$TOTAL" '[range($n)]')
MATRIX_JSON=$(jq -n -c --argjson n "$COUNT" '[range($n)]')

echo "Affected CI tasks: $TASK_COUNT, Runners: $TOTAL"
echo "count=$TOTAL" >> $GITHUB_OUTPUT
echo "Affected CI tasks: $TASK_COUNT, Runners: $COUNT"
echo "count=$COUNT" >> $GITHUB_OUTPUT
echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
24 changes: 24 additions & 0 deletions .github/actions/moon-ci-matrix/notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Smarter matrix would inlcude task to runner affinity by toolchain

# Get affected projects with their language
moon query projects --affected --json | jq '[.projects[] | {id, language}] | group_by(.language)'

Then your matrix becomes something like:

json
[
{"toolchain": "rust", "projects": ["parser", "wasm-bindings"]},
{"toolchain": "javascript", "projects": ["web", "docs"]}
]

Each shard runs moon ci scoped to its projects, so cargo only compiles once on the Rust runner and node_modules only installs on the JS runner.

Moon's query commands give you a lot to work with:

moon query projects --affected --json for affected projects with metadata

moon query tasks --affected --json for affected tasks

moon project-graph --json for the full dependency graph

You could even get fancier and look at the dependency graph to keep projects that depend on each other on the same runner. But grouping by language/toolchain gets you 90% of the benefit with minimal complexity. Worth prototyping once you have more than one project type in the repo.
2 changes: 0 additions & 2 deletions .github/actions/moon-ci/action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# .github/actions/moon-ci/action.yml
#
# Usage:
# - uses: ./.github/actions/moon-ci
# with:
Expand Down
31 changes: 19 additions & 12 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-action.json
#
# .github/actions/setup/action.yml
#
# Usage:
# - uses: ./.github/actions/setup
# with:
# cache-cargo: "true"
# cache-pnpm: "flase"
# cache-pnpm: "false"
#
# Usage (minimal, no project caches):
# - uses: ./.github/actions/setup
Expand All @@ -30,32 +32,37 @@ runs:
with:
fetch-depth: ${{ inputs.fetch-depth }}

- uses: moonrepo/setup-toolchain@v0
with:
auto-install: true

- uses: actions/cache@v4
with:
path: .moon/cache
key: moon-${{ runner.os }}-${{ hashFiles('.moon/workspace.yml', '.moon/tasks/*.yml', '.moon/toolchains.yml') }}
restore-keys: |
moon-${{ runner.os }}-

- uses: actions/cache@v4
if: inputs.cache-cargo == 'true'
with:
path: |
~/.cargo/bin
~/.cargo/registry
~/.cargo/git
target
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-

- name: Install cargo-binstall
shell: bash
run: command -v cargo-binstall || curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash

- uses: actions/cache@v4
with:
path: .moon/cache
key: moon-${{ runner.os }}-${{ hashFiles('.moon/workspace.yml', '.moon/tasks/*.yml', '.moon/toolchains.yml') }}
restore-keys: |
moon-${{ runner.os }}-

- uses: actions/cache@v4
if: inputs.cache-pnpm == 'true'
with:
path: ~/.local/share/pnpm/store
key: pnpm-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
pnpm-${{ runner.os }}-

- uses: moonrepo/setup-toolchain@v0
with:
auto-install: true
75 changes: 75 additions & 0 deletions .github/run-info.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
# Source this file: source run-debug.sh
# Then use: timing [run-id], logs [run-id], or just run directly for both

_resolve_run_id() {
local run_id="${1:-}"
if [[ -z "$run_id" ]]; then
run_id=$(gh run list --limit 1 --json databaseId --jq '.[0].databaseId')
echo "Using latest run: $run_id" >&2
fi
echo "$run_id"
}

timing() {
local run_id
run_id=$(_resolve_run_id "$1")

echo "=== Workflow Run: $run_id ==="
echo ""

gh run view "$run_id" --json jobs --jq '
.jobs | sort_by(.startedAt) | .[] |
"── \(.name) (\(.conclusion // "running")) ──",
" Started: \(.startedAt)",
" Duration: \(
if .completedAt then
((.completedAt | fromdateiso8601) - (.startedAt | fromdateiso8601)) as $dur |
"\($dur / 60 | floor)m \($dur % 60)s"
else "in progress"
end
)",
"",
(.steps | map(
(if .completedAt and .startedAt then
((.completedAt | fromdateiso8601) - (.startedAt | fromdateiso8601))
else 0 end) as $dur |
" \(if $dur >= 60 then "!!" elif $dur >= 30 then ">>" else " " end) \(
if .completedAt and .startedAt then
"\($dur / 60 | floor)m \($dur % 60 | tostring | if length < 2 then "0" + . else . end)s"
else "--:--"
end
) \(.conclusion // "---" | if . == "success" then "pass" elif . == "skipped" then "skip" elif . == "failure" then "FAIL" else . end) \(.name)"
) | join("\n")),
"",
""
'
}

logs() {
local run_id
run_id=$(_resolve_run_id "$1")
local outfile="run-${run_id}.log"

echo "Downloading logs for run $run_id..." >&2

gh run view "$run_id" --log > "$outfile" 2>&1

if [[ $? -eq 0 ]]; then
echo "Saved to $outfile ($(wc -l < "$outfile") lines)" >&2
echo "" >&2
echo "Quick search tips:" >&2
echo " grep -i error $outfile" >&2
echo " grep -i warn $outfile" >&2
echo " grep -iE 'fail|error|panic' $outfile" >&2
else
echo "Failed to download logs" >&2
cat "$outfile" >&2
fi
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
run_id=$(_resolve_run_id "$1")
timing "$run_id"
logs "$run_id"
fi
38 changes: 9 additions & 29 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
push:
branches: [main]

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

concurrency:
group: trunk-${{ github.sha }}
cancel-in-progress: false
Expand All @@ -16,17 +19,20 @@ jobs:
ci-matrix: ${{ steps.ci-matrix.outputs.matrix }}
runner-count: ${{ steps.ci-matrix.outputs.count }}
steps:
# Shallow checkout so GH Actions can resolve local composite actions.
# The setup action re-checks out with full history for moon's affected detection.
# TODO: Remove once composite actions are published to a shared repo.
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-depth: 1
- uses: ./.github/actions/setup
- id: ci-matrix
uses: ./.github/actions/moon-ci-matrix

ci:
name: Moon CI
needs: [config]
if: needs.config.outputs.runner-count > 0
if: ${{ fromJson(needs.config.outputs.runner-count || '0') > 0 }}
runs-on: ubuntu-latest
strategy:
fail-fast: true
Expand Down Expand Up @@ -68,35 +74,9 @@ jobs:
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3

semgrep:
name: Semgrep
needs: [ci]
runs-on: ubuntu-latest
permissions:
security-events: write
container:
image: returntocorp/semgrep
steps:
- uses: actions/checkout@v4
- name: Run Semgrep scan
run: |
semgrep ci \
--sarif --output=semgrep.sarif \
--config="p/default" \
--config="p/security-audit" \
--config="p/secrets"
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: semgrep.sarif
category: semgrep

release-please:
name: Release Please
needs: [ci, audit, codeql, semgrep]
needs: [ci, audit, codeql]
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/pr-close.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ on:
pull_request_target:
types: [closed]

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
teardown:
name: Review Teardown
runs-on: ubuntu-latest
permissions:
deployments: write
steps:
# Shallow checkout so GH Actions can resolve local composite actions.
# The setup action re-checks out with full history for moon's affected detection.
# TODO: Remove once composite actions are published to a shared repo.
- uses: actions/checkout@v4
with:
fetch-depth: 1
- uses: ./.github/actions/setup

- id: raa
Expand Down
Loading
Loading