Skip to content

Commit 2190a93

Browse files
mikkihugoclaude
andcommitted
feat: add enterprise-grade quality tooling and CLI binary
Add comprehensive quality assurance infrastructure: **Quality Tools & Configuration:** - Rust: Clippy (pedantic+nursery+cargo), cargo-audit, cargo-deny, cargo-geiger - Rust: cargo-tarpaulin, cargo-nextest, cargo-udeps, cargo-machete, cargo-bloat - Elixir: Credo, Dialyxir, Doctor, Sobelow, mix_audit, ExCoveralls - Security: gitleaks, shellcheck - Analysis: tokei, jscpd - Configuration files: clippy.toml, deny.toml, .credo.exs, .jscpd.json **CLI Binary (singularity-rca):** - Full-featured command-line interface with feature gates - Commands: analyze, metrics, languages, complexity, report, compare - Support for multiple output formats (table, json, csv, pretty) - Built with clap, anyhow, comfy-table, indicatif - Comprehensive documentation in CLI.md **Build & Development:** - Nix flake with all quality tools pre-installed - devenv.nix with pre-commit hooks (rustfmt, clippy, cargo-audit, credo) - justfile with quality targets (just quality runs everything) - Makefile alternative with same targets **GitHub Actions:** - Claude Code PR review automation (.github/workflows/claude-review.yml) - Claude Code interactive assistant (.github/workflows/claude.yml) - Enhanced CI with FlakeHub and Cachix caching - Release workflow builds CLI binary + source/binary tarballs **Documentation:** - CLI.md: Complete CLI usage guide - QUALITY.md: Quality tools and standards - SETUP.md: Development environment setup - CACHIX.md: Binary cache documentation **GitHub Secrets:** - CLAUDE_CODE_OAUTH_TOKEN - GH_TOKEN - CACHIX_AUTH_TOKEN - FLAKEHUB_PUSH_TOKEN All tools follow enterprise-grade standards with strict linting, security scanning, and comprehensive test coverage. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 595cdf7 commit 2190a93

26 files changed

+3333
-37
lines changed

.credo.exs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Credo Configuration for Singularity Analysis Engine
2+
# Enterprise-grade code quality standards for Elixir
3+
4+
%{
5+
configs: [
6+
%{
7+
name: "default",
8+
files: %{
9+
included: [
10+
"lib/",
11+
"src/",
12+
"test/",
13+
"web/",
14+
"apps/*/lib/",
15+
"apps/*/src/",
16+
"apps/*/test/",
17+
"apps/*/web/"
18+
],
19+
excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"]
20+
},
21+
plugins: [],
22+
requires: [],
23+
strict: true,
24+
parse_timeout: 5000,
25+
color: true,
26+
checks: %{
27+
enabled: [
28+
# Consistency Checks
29+
{Credo.Check.Consistency.ExceptionNames, []},
30+
{Credo.Check.Consistency.LineEndings, []},
31+
{Credo.Check.Consistency.ParameterPatternMatching, []},
32+
{Credo.Check.Consistency.SpaceAroundOperators, []},
33+
{Credo.Check.Consistency.SpaceInParentheses, []},
34+
{Credo.Check.Consistency.TabsOrSpaces, []},
35+
{Credo.Check.Consistency.UnusedVariableNames, []},
36+
37+
# Design Checks
38+
{Credo.Check.Design.AliasUsage,
39+
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]},
40+
{Credo.Check.Design.TagFIXME, [exit_status: 0]},
41+
{Credo.Check.Design.TagTODO, [exit_status: 0]},
42+
43+
# Readability Checks
44+
{Credo.Check.Readability.AliasOrder, []},
45+
{Credo.Check.Readability.FunctionNames, []},
46+
{Credo.Check.Readability.LargeNumbers, []},
47+
{Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]},
48+
{Credo.Check.Readability.ModuleAttributeNames, []},
49+
{Credo.Check.Readability.ModuleDoc, [priority: :high]},
50+
{Credo.Check.Readability.ModuleNames, []},
51+
{Credo.Check.Readability.ParenthesesInCondition, []},
52+
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
53+
{Credo.Check.Readability.PipeIntoAnonymousFunctions, []},
54+
{Credo.Check.Readability.PredicateFunctionNames, []},
55+
{Credo.Check.Readability.PreferImplicitTry, []},
56+
{Credo.Check.Readability.RedundantBlankLines, []},
57+
{Credo.Check.Readability.Semicolons, []},
58+
{Credo.Check.Readability.SpaceAfterCommas, []},
59+
{Credo.Check.Readability.StringSigils, []},
60+
{Credo.Check.Readability.TrailingBlankLine, []},
61+
{Credo.Check.Readability.TrailingWhiteSpace, []},
62+
{Credo.Check.Readability.UnnecessaryAliasExpansion, []},
63+
{Credo.Check.Readability.VariableNames, []},
64+
{Credo.Check.Readability.WithSingleClause, []},
65+
66+
# Refactoring Opportunities
67+
{Credo.Check.Refactor.Apply, []},
68+
{Credo.Check.Refactor.CondStatements, []},
69+
{Credo.Check.Refactor.CyclomaticComplexity, [max_complexity: 12]},
70+
{Credo.Check.Refactor.FilterCount, []},
71+
{Credo.Check.Refactor.FilterFilter, []},
72+
{Credo.Check.Refactor.FunctionArity, [max_arity: 6]},
73+
{Credo.Check.Refactor.LongQuoteBlocks, [max_line_count: 100]},
74+
{Credo.Check.Refactor.MapJoin, []},
75+
{Credo.Check.Refactor.MatchInCondition, []},
76+
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
77+
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
78+
{Credo.Check.Refactor.Nesting, [max_nesting: 3]},
79+
{Credo.Check.Refactor.RedundantWithClauseResult, []},
80+
{Credo.Check.Refactor.RejectReject, []},
81+
{Credo.Check.Refactor.UnlessWithElse, []},
82+
{Credo.Check.Refactor.WithClauses, []},
83+
84+
# Warning Checks
85+
{Credo.Check.Warning.ApplicationConfigInModuleAttribute, []},
86+
{Credo.Check.Warning.BoolOperationOnSameValues, []},
87+
{Credo.Check.Warning.Dbg, []},
88+
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
89+
{Credo.Check.Warning.IExPry, []},
90+
{Credo.Check.Warning.IoInspect, []},
91+
{Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []},
92+
{Credo.Check.Warning.OperationOnSameValues, []},
93+
{Credo.Check.Warning.OperationWithConstantResult, []},
94+
{Credo.Check.Warning.RaiseInsideRescue, []},
95+
{Credo.Check.Warning.SpecWithStruct, []},
96+
{Credo.Check.Warning.UnsafeExec, []},
97+
{Credo.Check.Warning.UnusedEnumOperation, []},
98+
{Credo.Check.Warning.UnusedFileOperation, []},
99+
{Credo.Check.Warning.UnusedKeywordOperation, []},
100+
{Credo.Check.Warning.UnusedListOperation, []},
101+
{Credo.Check.Warning.UnusedPathOperation, []},
102+
{Credo.Check.Warning.UnusedRegexOperation, []},
103+
{Credo.Check.Warning.UnusedStringOperation, []},
104+
{Credo.Check.Warning.UnusedTupleOperation, []},
105+
{Credo.Check.Warning.WrongTestFileExtension, []}
106+
],
107+
disabled: [
108+
# Optional/Opinionated checks that may be too strict
109+
{Credo.Check.Design.DuplicatedCode, []},
110+
{Credo.Check.Readability.AliasAs, []},
111+
{Credo.Check.Readability.BlockPipe, []},
112+
{Credo.Check.Readability.ImplTrue, []},
113+
{Credo.Check.Readability.MultiAlias, []},
114+
{Credo.Check.Readability.NestedFunctionCalls, []},
115+
{Credo.Check.Readability.OneArityFunctionInPipe, []},
116+
{Credo.Check.Readability.OnePipePerLine, []},
117+
{Credo.Check.Readability.SeparateAliasRequire, []},
118+
{Credo.Check.Readability.SingleFunctionToBlockPipe, []},
119+
{Credo.Check.Readability.SinglePipe, []},
120+
{Credo.Check.Readability.Specs, []},
121+
{Credo.Check.Readability.StrictModuleLayout, []},
122+
{Credo.Check.Readability.WithCustomTaggedTuple, []},
123+
{Credo.Check.Refactor.ABCSize, []},
124+
{Credo.Check.Refactor.AppendSingleItem, []},
125+
{Credo.Check.Refactor.DoubleBooleanNegation, []},
126+
{Credo.Check.Refactor.IoPuts, []},
127+
{Credo.Check.Refactor.MapInto, []},
128+
{Credo.Check.Refactor.MapMap, []},
129+
{Credo.Check.Refactor.ModuleDependencies, []},
130+
{Credo.Check.Refactor.NegatedIsNil, []},
131+
{Credo.Check.Refactor.PassAsyncInTestCases, []},
132+
{Credo.Check.Refactor.PipeChainStart, []},
133+
{Credo.Check.Refactor.RejectFilter, []},
134+
{Credo.Check.Refactor.VariableRebinding, []},
135+
{Credo.Check.Warning.LazyLogging, []},
136+
{Credo.Check.Warning.LeakyEnvironment, []},
137+
{Credo.Check.Warning.MapGetUnsafePass, []}
138+
]
139+
}
140+
}
141+
]
142+
}

.envrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ use flake
66
# Optional: Add any project-specific environment variables here
77
# export DATABASE_URL="postgresql://localhost/singularity_dev"
88

9+
# Load Cachix auth token and other secrets from .envrc.local if it exists
10+
if [ -f .envrc.local ]; then
11+
source .envrc.local
12+
fi
13+
914
# Optional: Load secrets from .env.local if it exists (not committed to git)
1015
if [ -f .env.local ]; then
1116
dotenv .env.local

.envrc.local.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Binary cache authentication tokens
2+
# Copy this file to .envrc.local and replace <TOKEN> placeholders with your actual tokens
3+
4+
# Cachix authentication token
5+
# Get your token from https://app.cachix.org/personal-auth-tokens
6+
export CACHIX_AUTH_TOKEN="<CACHIX_TOKEN>"
7+
8+
# FlakeHub authentication token
9+
# Get your token from https://flakehub.com/settings/tokens
10+
export FLAKEHUB_PUSH_TOKEN="<FLAKEHUB_TOKEN>"
11+
12+
# Example token formats (DO NOT COMMIT):
13+
# export CACHIX_AUTH_TOKEN="eyJhbGciOiJIUzI1NiJ9..."
14+
# export FLAKEHUB_PUSH_TOKEN="019a70a3-93a6-7f78-a389-45cf47e3bf30"

.github/workflows/ci.yml

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ jobs:
2323
contents: read
2424
steps:
2525
- uses: actions/checkout@v4
26+
- uses: cachix/install-nix-action@v30
27+
with:
28+
nix_path: nixpkgs=channel:nixos-unstable
29+
- name: Setup FlakeHub Cache
30+
uses: DeterminateSystems/flakehub-cache-action@v7
31+
with:
32+
cache-name: "singularity-analysis"
33+
visibility: "public"
34+
env:
35+
FLAKEHUB_PUSH_TOKEN: ${{ secrets.FLAKEHUB_PUSH_TOKEN }}
36+
- uses: cachix/cachix-action@v15
37+
with:
38+
name: mikkihugo
39+
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
2640
- uses: dtolnay/rust-toolchain@stable
2741
- uses: Swatinem/rust-cache@v2
2842
- name: Check compilation
@@ -37,6 +51,20 @@ jobs:
3751
contents: read
3852
steps:
3953
- uses: actions/checkout@v4
54+
- uses: cachix/install-nix-action@v30
55+
with:
56+
nix_path: nixpkgs=channel:nixos-unstable
57+
- name: Setup FlakeHub Cache
58+
uses: DeterminateSystems/flakehub-cache-action@v7
59+
with:
60+
cache-name: "singularity-analysis"
61+
visibility: "public"
62+
env:
63+
FLAKEHUB_PUSH_TOKEN: ${{ secrets.FLAKEHUB_PUSH_TOKEN }}
64+
- uses: cachix/cachix-action@v15
65+
with:
66+
name: mikkihugo
67+
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
4068
- uses: dtolnay/rust-toolchain@stable
4169
- uses: Swatinem/rust-cache@v2
4270
- name: Run tests
@@ -58,7 +86,7 @@ jobs:
5886
run: cargo fmt -- --check
5987

6088
clippy:
61-
name: Clippy
89+
name: Clippy (Strict)
6290
runs-on: ubuntu-latest
6391
container:
6492
image: mcr.microsoft.com/devcontainers/rust:1-bullseye
@@ -70,8 +98,21 @@ jobs:
7098
with:
7199
components: clippy
72100
- uses: Swatinem/rust-cache@v2
73-
- name: Run clippy
74-
run: cargo clippy --lib -- -D warnings
101+
- name: Run clippy with strictest settings
102+
run: |
103+
cargo clippy --workspace --all-targets --all-features -- \
104+
-D warnings \
105+
-D clippy::all \
106+
-D clippy::pedantic \
107+
-D clippy::nursery \
108+
-D clippy::cargo \
109+
-W clippy::restriction \
110+
-A clippy::missing_docs_in_private_items \
111+
-A clippy::implicit_return \
112+
-A clippy::missing_inline_in_public_items \
113+
-A clippy::question_mark_used \
114+
-A clippy::mod_module_files \
115+
-A clippy::self_named_module_files
75116
76117
build:
77118
name: Build Release
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Claude Code Review
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
issues: write
11+
12+
jobs:
13+
claude-review:
14+
runs-on: ubuntu-latest
15+
if: github.actor != 'dependabot[bot]'
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Get PR diff
23+
id: diff
24+
run: |
25+
git fetch origin ${{ github.base_ref }}
26+
git diff origin/${{ github.base_ref }}...${{ github.sha }} > pr-diff.txt
27+
echo "diff-size=$(wc -l < pr-diff.txt)" >> $GITHUB_OUTPUT
28+
29+
- name: Run Claude Code Review
30+
if: steps.diff.outputs.diff-size > 0
31+
env:
32+
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
33+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
34+
run: |
35+
# Install Claude Code if not available
36+
if ! command -v claude &> /dev/null; then
37+
curl -fsSL https://raw.githubusercontent.com/anthropics/claude-code/main/install.sh | sh
38+
fi
39+
40+
# Configure Claude Code
41+
export ANTHROPIC_API_KEY=$CLAUDE_CODE_OAUTH_TOKEN
42+
43+
# Review the PR
44+
claude review \
45+
--pr-number ${{ github.event.pull_request.number }} \
46+
--repo ${{ github.repository }} \
47+
--format markdown \
48+
> review-output.md
49+
50+
# Post review as comment
51+
gh pr comment ${{ github.event.pull_request.number }} \
52+
--body-file review-output.md \
53+
--repo ${{ github.repository }}
54+
55+
- name: Upload review artifacts
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: claude-review
59+
path: |
60+
pr-diff.txt
61+
review-output.md

.github/workflows/claude.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Claude Code Assistant
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request_review_comment:
7+
types: [created]
8+
9+
permissions:
10+
contents: write
11+
pull-requests: write
12+
issues: write
13+
14+
jobs:
15+
claude-assist:
16+
runs-on: ubuntu-latest
17+
if: |
18+
github.event_name == 'issue_comment' &&
19+
contains(github.event.comment.body, '@claude') &&
20+
github.event.issue.pull_request
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
with:
25+
ref: ${{ github.event.issue.pull_request.head.ref }}
26+
fetch-depth: 0
27+
28+
- name: Extract Claude command
29+
id: command
30+
run: |
31+
COMMENT="${{ github.event.comment.body }}"
32+
COMMAND=$(echo "$COMMENT" | grep -oP '@claude \K.*' || echo "help")
33+
echo "command=$COMMAND" >> $GITHUB_OUTPUT
34+
35+
- name: Run Claude Code
36+
env:
37+
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
39+
run: |
40+
# Install Claude Code if not available
41+
if ! command -v claude &> /dev/null; then
42+
curl -fsSL https://raw.githubusercontent.com/anthropics/claude-code/main/install.sh | sh
43+
fi
44+
45+
# Configure Claude Code
46+
export ANTHROPIC_API_KEY=$CLAUDE_CODE_OAUTH_TOKEN
47+
48+
# Execute command
49+
claude ${{ steps.command.outputs.command }} > claude-output.txt
50+
51+
- name: Commit changes if any
52+
run: |
53+
git config --local user.email "claude-bot@anthropic.com"
54+
git config --local user.name "Claude Code Bot"
55+
56+
if [[ -n $(git status -s) ]]; then
57+
git add -A
58+
git commit -m "feat: changes by Claude Code
59+
60+
@claude ${{ steps.command.outputs.command }}
61+
62+
Co-Authored-By: Claude <noreply@anthropic.com>"
63+
git push
64+
fi
65+
66+
- name: Post response
67+
env:
68+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
69+
run: |
70+
gh pr comment ${{ github.event.issue.number }} \
71+
--body-file claude-output.txt \
72+
--repo ${{ github.repository }}

0 commit comments

Comments
 (0)