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
12 changes: 12 additions & 0 deletions .clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Enforce “small functions” (Clean Code: 5–25 lines, allow a bit for Rust formatting)
too-many-lines-threshold = 30

# Enforce “2–3 params typical; 4+ suggests a data object” (Clean Code)
too-many-arguments-threshold = 4

# Complexity guardrail (closest analogue TS complexity/max-depth posture)
cognitive-complexity-threshold = 8

# Optional: approximate “max nesting depth 1–2”
# Note: this is structural nesting
excessive-nesting-threshold = 3
21 changes: 21 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@


text
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.rs]
indent_size = 4

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab
62 changes: 62 additions & 0 deletions .github/actions/conventional-pr/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# .github/actions/validate-pr-title/action.yml
#
# Usage:
# - uses: actions/checkout@v4
# - uses: ./.github/actions/validate-pr-title
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
#
# Usage (with extra scopes):
# - uses: ./.github/actions/validate-pr-title
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# extra-scopes: "infra,release"
#
# Scopes auto-discovered from .moon/workspace.yml projects list.
# deps, ci, repo are always included.

name: "Validate PR Title"
description: "Enforce conventional commit format on PR titles with auto-discovered scopes"

inputs:
github-token:
required: true
description: "GITHUB_TOKEN"
extra-scopes:
required: false
default: ""
description: "Comma-separated additional scopes beyond project names and builtins"

runs:
using: composite
steps:
- name: Discover project scopes
id: scopes
shell: bash
run: |
projects=$(yq '.workspace.projects // .projects |
if type == "!!seq" then .[] else keys[] end' .moon/workspace.yml 2>/dev/null | sort -u)

builtins="deps,ci,repo"
extra="${{ inputs.extra-scopes }}"
combined="${builtins}${extra:+,$extra}"

all_scopes=$(printf "%s\n%s" "$projects" "$(echo "$combined" | tr ',' '\n')" | sort -u)

echo "scopes<<EOF" >> "$GITHUB_OUTPUT"
echo "$all_scopes" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"

- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ inputs.github-token }}
with:
types: |
feat
fix
chore
docs
refactor
test
perf
scopes: ${{ steps.scopes.outputs.scopes }}
40 changes: 40 additions & 0 deletions .github/actions/moon-ci-matrix/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: "Moon CI Runner Matrix"
description: "Calculates optimal runner count from affected Moon tasks"

inputs:
tasks-per-runner:
required: false
default: "3"
description: "Number of affected tasks to assign per runner"
max-parallel:
required: false
default: "6"
description: "Maximum number of concurrent runners"

outputs:
matrix:
description: "JSON array of shard indices, e.g. [0, 1, 2]"
value: ${{ steps.calc.outputs.matrix }}
count:
description: "Total number of runners"
value: ${{ steps.calc.outputs.total }}

runs:
using: composite
steps:
- id: calc
shell: bash
run: |
TASKS_PER_RUNNER=${{ inputs.tasks-per-runner }}
MAX_RUNNERS=${{ inputs.max-parallel }}

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 ))

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

echo "Affected CI tasks: $TASK_COUNT, Runners: $TOTAL"
echo "count=$TOTAL" >> $GITHUB_OUTPUT
echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
32 changes: 32 additions & 0 deletions .github/actions/moon-ci/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# .github/actions/moon-ci/action.yml
#
# Usage:
# - uses: ./.github/actions/moon-ci
# with:
# access-token: ${{ secrets.GITHUB_TOKEN }}

name: "Moon CI"
description: "Run moon ci with sharding, reporting, and retrospect"

inputs:
access-token:
required: true
description: "GITHUB_TOKEN for run report"

runs:
using: composite
steps:
- name: Moon CI
shell: bash
run: |
echo "Runner ${{ strategy.job-index }} of ${{ strategy.job-total }}"
moon ci --color --job ${{ strategy.job-index }} --job-total ${{ strategy.job-total }}

- uses: moonrepo/run-report-action@v1
if: success() || failure()
with:
access-token: ${{ inputs.access-token }}
matrix: '{"index": ${{ strategy.job-index }}, "total": ${{ strategy.job-total }}}'

- uses: appthrust/moon-ci-retrospect@v1
if: success() || failure()
57 changes: 57 additions & 0 deletions .github/actions/moon-raa/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: "moon-raa"
description: "Manage review apps and artifacts for a Moon monorepo"

inputs:
command:
required: true
description: "'run' or 'rm'"
pr-number:
required: true
description: "PR number"
prefix:
required: false
default: "raa"
description: "Environment name prefix (prepended to '-pr-{number}')"
github-token:
required: true
description: "GITHUB_TOKEN"

outputs:
deployment-id:
description: "GitHub Deployment ID (run only)"
value: ${{ steps.raa.outputs.deployment-id }}
environment:
description: "Environment name"
value: ${{ steps.raa.outputs.environment }}
project-count:
description: "Number of projects processed"
value: ${{ steps.raa.outputs.project-count }}
summary:
description: "Markdown summary for GITHUB_STEP_SUMMARY"
value: ${{ steps.raa.outputs.summary }}
manifest:
description: "Full payload as JSON"
value: ${{ steps.raa.outputs.manifest }}
clean:
description: "true if rm completed without warnings (rm only)"
value: ${{ steps.raa.outputs.clean }}

runs:
using: composite
steps:
- name: moon-raa
id: raa
uses: actions/github-script@v7
env:
INPUT_COMMAND: ${{ inputs.command }}
INPUT_PR_NUMBER: ${{ inputs.pr-number }}
INPUT_PREFIX: ${{ inputs.prefix }}
with:
github-token: ${{ inputs.github-token }}
script: |
const cmd = process.env.INPUT_COMMAND;
const handler = require(`${{ github.action_path }}/${cmd}.js`);
await handler({ github, context, core, exec, inputs: {
pr_number: process.env.INPUT_PR_NUMBER,
prefix: process.env.INPUT_PREFIX,
}});
139 changes: 139 additions & 0 deletions .github/actions/moon-raa/lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
const environmentName = (prefix, prNumber) => `${prefix}-pr-${prNumber}`

const artifactName = (prefix, projectId, prNumber) => `${prefix}-${projectId}-pr-${prNumber}`

const targetName = (projectId, task) => `${projectId}:${task}`

const buildManifest = (prNumber, projects) => ({ pr_number: prNumber, projects })

const buildProjectEntry = (prefix, prNumber) => project => ({
id: project.id,
artifact_name: artifactName(prefix, project.id, prNumber),
run: project.raa.run,
rm: project.raa.rm,
})

const validateProject = project => {
const raa = project.raa
const missing = [!raa && 'raa metadata', raa && !raa.run && 'raa.run', raa && !raa.rm && 'raa.rm'].filter(
Boolean,
)

return missing.length ? { valid: false, reason: `missing ${missing.join(', ')}` } : { valid: true }
}

const partitionProjects = (projects, core) => {
const valid = []
for (const project of projects) {
const result = validateProject(project)
if (!result.valid) {
core.warning(`Skipping ${project.id}: ${result.reason}`)
continue
}
valid.push(project)
}
return valid
}

const formatRunSummary = (environment, projects) => {
if (!projects.length) return 'No RAA projects affected.'

const rows = projects.map(p => `| ${p.id} | \`${p.run}\` | \`${p.artifact_name}\` |`).join('\n')

return [
`### RAA Review`,
'',
'| Project | Task | Artifact |',
'|---------|------|----------|',
rows,
'',
`${projects.length} project(s) deployed to \`${environment}\``,
].join('\n')
}

const formatRmSummary = (environment, results) => {
if (!results.length) return 'No RAA projects to tear down.'

const rows = results.map(r => `| ${r.id} | \`${r.rm}\` | ${r.status} |`).join('\n')

return [
`### RAA Teardown`,
'',
'| Project | Task | Status |',
'|---------|------|--------|',
rows,
'',
`${results.length} project(s) torn down from \`${environment}\``,
].join('\n')
}

const listDeployments = async (github, owner, repo, environment) => {
const { data } = await github.rest.repos.listDeployments({ owner, repo, environment })
return data
}

const deactivateDeployments = async (github, owner, repo, environment, core) => {
const deployments = await listDeployments(github, owner, repo, environment)

for (const deployment of deployments) {
await github.rest.repos.createDeploymentStatus({
owner,
repo,
deployment_id: deployment.id,
state: 'inactive',
})
await github.rest.repos.deleteDeployment({ owner, repo, deployment_id: deployment.id })
core.info(`Deactivated and deleted deployment ${deployment.id}`)
}

return deployments
}

const createDeployment = async (github, owner, repo, { ref, environment, description, payload }) => {
const { data: deployment } = await github.rest.repos.createDeployment({
owner,
repo,
ref,
environment,
auto_merge: false,
required_contexts: [],
description,
payload: JSON.stringify(payload),
})
return deployment
}

const setDeploymentStatus = async (github, owner, repo, deploymentId, state, description) => {
await github.rest.repos.createDeploymentStatus({
owner,
repo,
deployment_id: deploymentId,
state,
description: description ?? '',
})
}

const deleteEnvironment = async (github, owner, repo, environment) => {
try {
await github.rest.repos.deleteAnEnvironment({ owner, repo, environment_name: environment })
} catch (error) {
if (error.status !== 404) throw error
}
}

module.exports = {
environmentName,
artifactName,
targetName,
buildManifest,
buildProjectEntry,
validateProject,
partitionProjects,
formatRunSummary,
formatRmSummary,
listDeployments,
deactivateDeployments,
createDeployment,
setDeploymentStatus,
deleteEnvironment,
}
Loading
Loading