@geraldmaron/construct 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +69 -0
- package/LICENSE +21 -0
- package/README.md +344 -0
- package/agents/prompts/cx-accessibility.md +29 -0
- package/agents/prompts/cx-ai-engineer.md +31 -0
- package/agents/prompts/cx-architect.md +40 -0
- package/agents/prompts/cx-business-strategist.md +25 -0
- package/agents/prompts/cx-data-analyst.md +30 -0
- package/agents/prompts/cx-data-engineer.md +32 -0
- package/agents/prompts/cx-debugger.md +27 -0
- package/agents/prompts/cx-designer.md +33 -0
- package/agents/prompts/cx-devil-advocate.md +36 -0
- package/agents/prompts/cx-docs-keeper.md +50 -0
- package/agents/prompts/cx-engineer.md +36 -0
- package/agents/prompts/cx-evaluator.md +26 -0
- package/agents/prompts/cx-explorer.md +38 -0
- package/agents/prompts/cx-legal-compliance.md +25 -0
- package/agents/prompts/cx-operations.md +28 -0
- package/agents/prompts/cx-orchestrator.md +30 -0
- package/agents/prompts/cx-platform-engineer.md +25 -0
- package/agents/prompts/cx-product-manager.md +30 -0
- package/agents/prompts/cx-qa.md +42 -0
- package/agents/prompts/cx-rd-lead.md +25 -0
- package/agents/prompts/cx-release-manager.md +31 -0
- package/agents/prompts/cx-researcher.md +31 -0
- package/agents/prompts/cx-reviewer.md +36 -0
- package/agents/prompts/cx-security.md +37 -0
- package/agents/prompts/cx-sre.md +26 -0
- package/agents/prompts/cx-test-automation.md +35 -0
- package/agents/prompts/cx-trace-reviewer.md +76 -0
- package/agents/prompts/cx-ux-researcher.md +30 -0
- package/agents/registry.json +879 -0
- package/agents/teams.json +94 -0
- package/bin/construct +613 -0
- package/commands/build/feature.md +21 -0
- package/commands/build/fix.md +20 -0
- package/commands/design/access.md +19 -0
- package/commands/design/flow.md +16 -0
- package/commands/design/ui.md +18 -0
- package/commands/measure/experiment.md +18 -0
- package/commands/measure/metrics.md +18 -0
- package/commands/measure/results.md +18 -0
- package/commands/plan/api.md +19 -0
- package/commands/plan/challenge.md +18 -0
- package/commands/plan/decide.md +20 -0
- package/commands/plan/feature.md +49 -0
- package/commands/plan/requirements.md +24 -0
- package/commands/remember/context.md +26 -0
- package/commands/remember/handoff.md +19 -0
- package/commands/remember/runbook.md +20 -0
- package/commands/review/code.md +21 -0
- package/commands/review/quality.md +19 -0
- package/commands/review/security.md +16 -0
- package/commands/ship/ready.md +19 -0
- package/commands/ship/release.md +19 -0
- package/commands/ship/status.md +18 -0
- package/commands/understand/docs.md +22 -0
- package/commands/understand/research.md +22 -0
- package/commands/understand/this.md +23 -0
- package/commands/understand/why.md +18 -0
- package/commands/work/clean.md +32 -0
- package/commands/work/drive.md +69 -0
- package/commands/work/optimize-prompts.md +46 -0
- package/commands/work/parallel-review.md +40 -0
- package/db/migrations/001_init.sql +38 -0
- package/langfuse/docker-compose.yml +82 -0
- package/lib/audit-skills.mjs +118 -0
- package/lib/auto-docs.mjs +293 -0
- package/lib/cli-commands.mjs +409 -0
- package/lib/codex-config.mjs +114 -0
- package/lib/comment-lint.mjs +191 -0
- package/lib/completions.mjs +170 -0
- package/lib/context-state.mjs +99 -0
- package/lib/cost.mjs +213 -0
- package/lib/distill.mjs +403 -0
- package/lib/efficiency.mjs +139 -0
- package/lib/env-config.mjs +53 -0
- package/lib/eval-harness.mjs +59 -0
- package/lib/features.mjs +209 -0
- package/lib/headhunt.mjs +597 -0
- package/lib/hooks/adaptive-lint.mjs +112 -0
- package/lib/hooks/agent-tracker.mjs +50 -0
- package/lib/hooks/bootstrap-guard.mjs +90 -0
- package/lib/hooks/comment-lint.mjs +26 -0
- package/lib/hooks/config-protection.mjs +52 -0
- package/lib/hooks/console-warn.mjs +43 -0
- package/lib/hooks/context-window-recovery.mjs +90 -0
- package/lib/hooks/continuation-enforcer.mjs +72 -0
- package/lib/hooks/dep-audit.mjs +155 -0
- package/lib/hooks/drive-guard.mjs +89 -0
- package/lib/hooks/edit-accumulator.mjs +36 -0
- package/lib/hooks/edit-error-recovery.mjs +46 -0
- package/lib/hooks/edit-guard.mjs +109 -0
- package/lib/hooks/env-check.mjs +80 -0
- package/lib/hooks/guard-bash.mjs +83 -0
- package/lib/hooks/mcp-audit.mjs +57 -0
- package/lib/hooks/mcp-health-check.mjs +51 -0
- package/lib/hooks/mcp-task-scope.mjs +47 -0
- package/lib/hooks/model-fallback.mjs +105 -0
- package/lib/hooks/pre-compact.mjs +212 -0
- package/lib/hooks/pre-push-gate.mjs +129 -0
- package/lib/hooks/read-tracker.mjs +129 -0
- package/lib/hooks/registry-sync.mjs +23 -0
- package/lib/hooks/scan-secrets.mjs +76 -0
- package/lib/hooks/session-start.mjs +95 -0
- package/lib/hooks/stop-notify.mjs +191 -0
- package/lib/hooks/stop-typecheck.mjs +83 -0
- package/lib/hooks/task-completed-guard.mjs +43 -0
- package/lib/hooks/teammate-idle-guard.mjs +54 -0
- package/lib/hooks/workflow-guard.mjs +62 -0
- package/lib/host-capabilities.mjs +123 -0
- package/lib/init-docs.mjs +382 -0
- package/lib/mcp/server.mjs +1123 -0
- package/lib/mcp-catalog.json +243 -0
- package/lib/mcp-manager.mjs +433 -0
- package/lib/mcp-platform-config.mjs +104 -0
- package/lib/model-router.mjs +810 -0
- package/lib/opencode-config.mjs +44 -0
- package/lib/opencode-runtime-plugin.mjs +909 -0
- package/lib/opencode-telemetry.mjs +433 -0
- package/lib/orchestration-policy.mjs +258 -0
- package/lib/prompt-composer.mjs +196 -0
- package/lib/prompt-metadata.mjs +68 -0
- package/lib/review.mjs +429 -0
- package/lib/role-preload.mjs +52 -0
- package/lib/schemas/decision.json +50 -0
- package/lib/schemas/implementation.json +51 -0
- package/lib/schemas/review-report.json +32 -0
- package/lib/schemas/test-report.json +43 -0
- package/lib/server/index.mjs +334 -0
- package/lib/server/static/app.js +841 -0
- package/lib/server/static/index.html +820 -0
- package/lib/service-manager.mjs +225 -0
- package/lib/setup.mjs +319 -0
- package/lib/status.mjs +707 -0
- package/lib/storage/backend.mjs +44 -0
- package/lib/storage/embeddings.mjs +70 -0
- package/lib/storage/hybrid-query.mjs +184 -0
- package/lib/storage/sql-store.mjs +55 -0
- package/lib/storage/state-source.mjs +101 -0
- package/lib/storage/sync.mjs +164 -0
- package/lib/storage/vector-store.mjs +59 -0
- package/lib/telemetry/backends/langfuse.mjs +58 -0
- package/lib/telemetry/backends/noop.mjs +16 -0
- package/lib/telemetry/langfuse-ingest.mjs +108 -0
- package/lib/telemetry/langfuse-model-sync.mjs +270 -0
- package/lib/telemetry/team-rollup.mjs +143 -0
- package/lib/toolkit-env.mjs +30 -0
- package/lib/validator.mjs +181 -0
- package/lib/workflow-state.mjs +794 -0
- package/package.json +53 -0
- package/personas/construct.md +94 -0
- package/platforms/claude/CLAUDE.md +30 -0
- package/platforms/claude/settings.template.json +472 -0
- package/platforms/opencode/config.template.json +65 -0
- package/platforms/opencode/plugins/construct-fallback.js +5 -0
- package/platforms/opencode/sync-config.mjs +69 -0
- package/rules/common/agents.md +55 -0
- package/rules/common/code-review.md +129 -0
- package/rules/common/coding-style.md +95 -0
- package/rules/common/comments.md +139 -0
- package/rules/common/cx-agent-routing.md +61 -0
- package/rules/common/cx-skill-routing.md +11 -0
- package/rules/common/development-workflow.md +49 -0
- package/rules/common/git-workflow.md +29 -0
- package/rules/common/hooks.md +35 -0
- package/rules/common/patterns.md +36 -0
- package/rules/common/performance.md +71 -0
- package/rules/common/security.md +34 -0
- package/rules/common/testing.md +62 -0
- package/rules/golang/coding-style.md +37 -0
- package/rules/golang/hooks.md +22 -0
- package/rules/golang/patterns.md +50 -0
- package/rules/golang/security.md +39 -0
- package/rules/golang/testing.md +36 -0
- package/rules/python/coding-style.md +47 -0
- package/rules/python/hooks.md +24 -0
- package/rules/python/patterns.md +44 -0
- package/rules/python/security.md +35 -0
- package/rules/python/testing.md +43 -0
- package/rules/swift/coding-style.md +52 -0
- package/rules/swift/hooks.md +25 -0
- package/rules/swift/patterns.md +71 -0
- package/rules/swift/security.md +38 -0
- package/rules/swift/testing.md +50 -0
- package/rules/typescript/coding-style.md +204 -0
- package/rules/typescript/hooks.md +27 -0
- package/rules/typescript/patterns.md +57 -0
- package/rules/typescript/security.md +33 -0
- package/rules/typescript/testing.md +23 -0
- package/rules/web/coding-style.md +101 -0
- package/rules/web/design-quality.md +68 -0
- package/rules/web/hooks.md +125 -0
- package/rules/web/patterns.md +84 -0
- package/rules/web/performance.md +69 -0
- package/rules/web/security.md +62 -0
- package/rules/web/testing.md +60 -0
- package/rules/zh/README.md +113 -0
- package/rules/zh/agents.md +55 -0
- package/rules/zh/code-review.md +129 -0
- package/rules/zh/coding-style.md +53 -0
- package/rules/zh/development-workflow.md +49 -0
- package/rules/zh/git-workflow.md +29 -0
- package/rules/zh/hooks.md +35 -0
- package/rules/zh/patterns.md +36 -0
- package/rules/zh/performance.md +60 -0
- package/rules/zh/security.md +34 -0
- package/rules/zh/testing.md +34 -0
- package/skills/ai/agent-dev.md +102 -0
- package/skills/ai/llm-security.md +105 -0
- package/skills/ai/ml-ops.md +169 -0
- package/skills/ai/orchestration-workflow.md +87 -0
- package/skills/ai/prompt-and-eval.md +114 -0
- package/skills/ai/prompt-optimizer.md +114 -0
- package/skills/ai/rag-system.md +104 -0
- package/skills/architecture/api-design.md +100 -0
- package/skills/architecture/caching.md +101 -0
- package/skills/architecture/cloud-native.md +97 -0
- package/skills/architecture/message-queue.md +100 -0
- package/skills/architecture/security-arch.md +105 -0
- package/skills/development/cpp.md +127 -0
- package/skills/development/go.md +129 -0
- package/skills/development/java.md +134 -0
- package/skills/development/kotlin.md +140 -0
- package/skills/development/mobile-crossplatform.md +144 -0
- package/skills/development/python.md +109 -0
- package/skills/development/rust.md +127 -0
- package/skills/development/shell.md +127 -0
- package/skills/development/swift.md +129 -0
- package/skills/development/typescript.md +129 -0
- package/skills/devops/ci-cd.md +108 -0
- package/skills/devops/containerization.md +106 -0
- package/skills/devops/cost-optimization.md +105 -0
- package/skills/devops/data-engineering.md +181 -0
- package/skills/devops/database.md +95 -0
- package/skills/devops/dependency-management.md +91 -0
- package/skills/devops/devsecops.md +96 -0
- package/skills/devops/git-workflow.md +100 -0
- package/skills/devops/incident-response.md +167 -0
- package/skills/devops/monorepo.md +87 -0
- package/skills/devops/observability.md +103 -0
- package/skills/devops/performance.md +104 -0
- package/skills/devops/testing.md +104 -0
- package/skills/docs/adr-workflow.md +32 -0
- package/skills/docs/backlog-proposal-workflow.md +19 -0
- package/skills/docs/customer-profile-workflow.md +22 -0
- package/skills/docs/evidence-ingest-workflow.md +23 -0
- package/skills/docs/init-docs.md +160 -0
- package/skills/docs/init-project.md +50 -0
- package/skills/docs/prd-workflow.md +57 -0
- package/skills/docs/prfaq-workflow.md +25 -0
- package/skills/docs/product-intelligence-review.md +22 -0
- package/skills/docs/product-intelligence-workflow.md +62 -0
- package/skills/docs/product-signal-workflow.md +27 -0
- package/skills/docs/research-workflow.md +28 -0
- package/skills/docs/runbook-workflow.md +24 -0
- package/skills/exploration/repo-map.md +297 -0
- package/skills/frameworks/django.md +159 -0
- package/skills/frameworks/nextjs.md +148 -0
- package/skills/frameworks/react.md +132 -0
- package/skills/frameworks/spring-boot.md +165 -0
- package/skills/frontend-design/accessibility.md +153 -0
- package/skills/frontend-design/component-patterns.md +111 -0
- package/skills/frontend-design/engineering.md +122 -0
- package/skills/frontend-design/state-management.md +118 -0
- package/skills/frontend-design/ui-aesthetics.md +102 -0
- package/skills/frontend-design/ux-principles.md +126 -0
- package/skills/quality-gates/review-work.md +90 -0
- package/skills/quality-gates/verify-change.md +94 -0
- package/skills/quality-gates/verify-module.md +96 -0
- package/skills/quality-gates/verify-quality.md +93 -0
- package/skills/quality-gates/verify-security.md +95 -0
- package/skills/roles/architect.ai-systems.md +37 -0
- package/skills/roles/architect.data.md +37 -0
- package/skills/roles/architect.enterprise.md +37 -0
- package/skills/roles/architect.integration.md +37 -0
- package/skills/roles/architect.md +68 -0
- package/skills/roles/architect.platform.md +37 -0
- package/skills/roles/data-analyst.experiment.md +37 -0
- package/skills/roles/data-analyst.md +68 -0
- package/skills/roles/data-analyst.product-intelligence.md +37 -0
- package/skills/roles/data-analyst.product.md +37 -0
- package/skills/roles/data-analyst.telemetry.md +37 -0
- package/skills/roles/data-engineer.pipeline.md +37 -0
- package/skills/roles/data-engineer.vector-retrieval.md +37 -0
- package/skills/roles/data-engineer.warehouse.md +37 -0
- package/skills/roles/debugger.md +68 -0
- package/skills/roles/designer.accessibility.md +43 -0
- package/skills/roles/designer.md +68 -0
- package/skills/roles/engineer.ai.md +49 -0
- package/skills/roles/engineer.data.md +49 -0
- package/skills/roles/engineer.md +85 -0
- package/skills/roles/engineer.platform.md +49 -0
- package/skills/roles/operator.docs.md +43 -0
- package/skills/roles/operator.md +68 -0
- package/skills/roles/operator.release.md +43 -0
- package/skills/roles/operator.sre.md +43 -0
- package/skills/roles/orchestrator.md +66 -0
- package/skills/roles/product-manager.ai-product.md +37 -0
- package/skills/roles/product-manager.business-strategy.md +43 -0
- package/skills/roles/product-manager.enterprise.md +37 -0
- package/skills/roles/product-manager.growth.md +37 -0
- package/skills/roles/product-manager.md +67 -0
- package/skills/roles/product-manager.platform.md +37 -0
- package/skills/roles/product-manager.product.md +37 -0
- package/skills/roles/qa.ai-eval.md +37 -0
- package/skills/roles/qa.api-contract.md +37 -0
- package/skills/roles/qa.data-pipeline.md +37 -0
- package/skills/roles/qa.md +68 -0
- package/skills/roles/qa.test-automation.md +49 -0
- package/skills/roles/qa.web-ui.md +37 -0
- package/skills/roles/researcher.explorer.md +43 -0
- package/skills/roles/researcher.md +68 -0
- package/skills/roles/researcher.ux.md +43 -0
- package/skills/roles/reviewer.devil-advocate.md +43 -0
- package/skills/roles/reviewer.evaluator.md +43 -0
- package/skills/roles/reviewer.md +68 -0
- package/skills/roles/reviewer.trace.md +43 -0
- package/skills/roles/security.ai.md +37 -0
- package/skills/roles/security.appsec.md +37 -0
- package/skills/roles/security.cloud.md +37 -0
- package/skills/roles/security.legal-compliance.md +49 -0
- package/skills/roles/security.md +68 -0
- package/skills/roles/security.privacy.md +37 -0
- package/skills/roles/security.supply-chain.md +37 -0
- package/skills/routing.md +139 -0
- package/skills/security/blue-team.md +83 -0
- package/skills/security/code-audit.md +94 -0
- package/skills/security/pentest.md +84 -0
- package/skills/security/red-team.md +81 -0
- package/skills/security/threat-intel.md +89 -0
- package/skills/security/vuln-research.md +87 -0
- package/skills/utility/clean-code.md +165 -0
- package/sync-agents.mjs +899 -0
- package/templates/docs/adr.md +27 -0
- package/templates/docs/backlog-proposal.md +26 -0
- package/templates/docs/customer-profile.md +34 -0
- package/templates/docs/evidence-brief.md +37 -0
- package/templates/docs/incident-report.md +46 -0
- package/templates/docs/memo.md +27 -0
- package/templates/docs/meta-prd.md +56 -0
- package/templates/docs/one-pager.md +24 -0
- package/templates/docs/prd-business.md +61 -0
- package/templates/docs/prd-platform.md +62 -0
- package/templates/docs/prd.md +47 -0
- package/templates/docs/prfaq.md +31 -0
- package/templates/docs/product-intelligence-report.md +31 -0
- package/templates/docs/research-brief.md +29 -0
- package/templates/docs/rfc-platform.md +60 -0
- package/templates/docs/rfc.md +46 -0
- package/templates/docs/runbook.md +33 -0
- package/templates/docs/signal-brief.md +25 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/development/shell.md — Shell Scripting Best Practices — Use this skill when writing, reviewing, or debugging Bash, Zsh, or POSIX shell s
|
|
3
|
+
|
|
4
|
+
Use this skill when writing, reviewing, or debugging Bash, Zsh, or POSIX shell scripts. ## Script Header
|
|
5
|
+
-->
|
|
6
|
+
# Shell Scripting Best Practices
|
|
7
|
+
|
|
8
|
+
Use this skill when writing, reviewing, or debugging Bash, Zsh, or POSIX shell scripts.
|
|
9
|
+
|
|
10
|
+
## Script Header
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
#!/usr/bin/env bash
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- `set -e`: exit on error
|
|
18
|
+
- `set -u`: treat unset variables as errors
|
|
19
|
+
- `set -o pipefail`: propagate pipe failures
|
|
20
|
+
- Use `#!/usr/bin/env bash` for portability; `#!/bin/sh` for POSIX-only scripts
|
|
21
|
+
|
|
22
|
+
## Variables
|
|
23
|
+
|
|
24
|
+
- Always quote variables: `"$var"` prevents word splitting and globbing
|
|
25
|
+
- Use `${var:-default}` for default values
|
|
26
|
+
- Use `${var:?error message}` to fail on unset required variables
|
|
27
|
+
- Local variables in functions: `local var="value"`
|
|
28
|
+
- Uppercase for exported/environment variables; lowercase for script-local
|
|
29
|
+
|
|
30
|
+
## Functions
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
function_name() {
|
|
34
|
+
local input="$1"
|
|
35
|
+
# function body
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- Use functions for any logic reused or exceeding 10 lines
|
|
40
|
+
- Declare local variables with `local`
|
|
41
|
+
- Return exit codes (0 = success, non-zero = failure)
|
|
42
|
+
- Use `return` for status; use stdout for data output
|
|
43
|
+
|
|
44
|
+
## Conditionals and Testing
|
|
45
|
+
|
|
46
|
+
- `[[ ]]` for conditionals in Bash (safer than `[ ]`)
|
|
47
|
+
- `(( ))` for arithmetic comparisons
|
|
48
|
+
- String comparison: `[[ "$a" == "$b" ]]`
|
|
49
|
+
- File tests: `[[ -f "$file" ]]`, `[[ -d "$dir" ]]`, `[[ -r "$file" ]]`
|
|
50
|
+
- Regex: `[[ "$str" =~ ^pattern$ ]]`
|
|
51
|
+
- Always quote variables inside conditionals
|
|
52
|
+
|
|
53
|
+
## Input Handling
|
|
54
|
+
|
|
55
|
+
- Validate all arguments before processing
|
|
56
|
+
- Use `getopts` or manual parsing for flags
|
|
57
|
+
- Provide usage/help output with `--help`
|
|
58
|
+
- Check required tools exist: `command -v tool >/dev/null || { echo "tool required"; exit 1; }`
|
|
59
|
+
- Sanitize any input used in commands to prevent injection
|
|
60
|
+
|
|
61
|
+
## Error Handling
|
|
62
|
+
|
|
63
|
+
- Use `trap` for cleanup: `trap cleanup EXIT`
|
|
64
|
+
- Check command return codes explicitly for critical operations
|
|
65
|
+
- Log errors to stderr: `echo "Error: message" >&2`
|
|
66
|
+
- Exit with meaningful codes: 1 = general error, 2 = usage error
|
|
67
|
+
- Use `|| true` only when a failure is genuinely acceptable
|
|
68
|
+
|
|
69
|
+
## Temporary Files
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
tmpdir=$(mktemp -d)
|
|
73
|
+
trap 'rm -rf "$tmpdir"' EXIT
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- Always use `mktemp` for temporary files and directories
|
|
77
|
+
- Clean up with EXIT trap
|
|
78
|
+
- Never hardcode temporary paths
|
|
79
|
+
|
|
80
|
+
## Process and Subshell
|
|
81
|
+
|
|
82
|
+
- `$()` for command substitution (not backticks)
|
|
83
|
+
- Avoid unnecessary subshells; they add overhead
|
|
84
|
+
- Use `read` with `IFS` for parsing: `IFS=: read -r user pass <<< "$line"`
|
|
85
|
+
- Process substitution `<()` for feeding command output as a file
|
|
86
|
+
- `xargs` or `while read` for processing lists; avoid `for f in $(ls)`
|
|
87
|
+
|
|
88
|
+
## Portability
|
|
89
|
+
|
|
90
|
+
- Test on the target shell (Bash 3.x on macOS, 5.x on Linux)
|
|
91
|
+
- Avoid Bash-specific features in `#!/bin/sh` scripts
|
|
92
|
+
- Use `printf` over `echo` for consistent behavior across platforms
|
|
93
|
+
- Check for GNU vs BSD tool differences (sed, date, grep flags)
|
|
94
|
+
|
|
95
|
+
## Security
|
|
96
|
+
|
|
97
|
+
- Never use `eval` with user input
|
|
98
|
+
- Quote all variable expansions
|
|
99
|
+
- Use `--` to terminate option parsing before user input: `grep -- "$pattern" file`
|
|
100
|
+
- Validate file paths; prevent directory traversal
|
|
101
|
+
- Avoid storing secrets in variables visible in `/proc` or `ps` output
|
|
102
|
+
- Use `mktemp` with restrictive permissions
|
|
103
|
+
|
|
104
|
+
## Testing
|
|
105
|
+
|
|
106
|
+
- Use `bats` (Bash Automated Testing System) for shell script tests
|
|
107
|
+
- Test exit codes, stdout, and stderr output
|
|
108
|
+
- Test with various inputs: empty, spaces, special characters, long strings
|
|
109
|
+
- Run with `shellcheck` for static analysis; fix all warnings
|
|
110
|
+
- Test on CI with the target shell version
|
|
111
|
+
|
|
112
|
+
## Performance
|
|
113
|
+
|
|
114
|
+
- Avoid unnecessary external commands; use Bash builtins when possible
|
|
115
|
+
- `[[ ]]` is faster than `[ ]` (no separate process)
|
|
116
|
+
- Parameter expansion (`${var##*/}`) over `basename "$var"`
|
|
117
|
+
- Bulk operations over loops: `find ... -exec cmd {} +` over `for f in; do cmd "$f"; done`
|
|
118
|
+
- If performance matters significantly, consider Python or Go instead
|
|
119
|
+
|
|
120
|
+
## Anti-Patterns
|
|
121
|
+
|
|
122
|
+
- Parsing `ls` output (use glob patterns or `find`)
|
|
123
|
+
- Unquoted variable expansions
|
|
124
|
+
- `cat file | grep` instead of `grep pattern file`
|
|
125
|
+
- `cd` without checking success: use `cd dir || exit 1`
|
|
126
|
+
- Scripts longer than 200 lines without functions
|
|
127
|
+
- Storing structured data in variables (use files or jq for JSON)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/development/swift.md — Swift / iOS Development — Swift 6 enforces data-race safety at compile time. Annotate isolation boundary e
|
|
3
|
+
|
|
4
|
+
## Concurrency (Swift 6 Strict Concurrency) Swift 6 enforces data-race safety at compile time. Annotate isolation boundary explicitly:
|
|
5
|
+
-->
|
|
6
|
+
# Swift / iOS Development
|
|
7
|
+
|
|
8
|
+
## Concurrency (Swift 6 Strict Concurrency)
|
|
9
|
+
|
|
10
|
+
Swift 6 enforces data-race safety at compile time. Annotate isolation boundary explicitly:
|
|
11
|
+
|
|
12
|
+
```swift
|
|
13
|
+
@MainActor
|
|
14
|
+
final class ViewModel: ObservableObject {
|
|
15
|
+
@Published var items: [Item] = []
|
|
16
|
+
|
|
17
|
+
func load() async {
|
|
18
|
+
items = await repository.fetchAll()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Key rules:
|
|
24
|
+
- `@MainActor` for all UI-touching types
|
|
25
|
+
- `actor` for shared mutable state accessed off the main thread
|
|
26
|
+
- `Sendable` conformance on types crossing isolation boundaries
|
|
27
|
+
- Prefer `async/await` over completion handlers; avoid mixing the two
|
|
28
|
+
|
|
29
|
+
Common pitfall: `Task { }` inherits the actor context of its caller — do not assume it runs on a background thread.
|
|
30
|
+
|
|
31
|
+
## SwiftUI Patterns
|
|
32
|
+
|
|
33
|
+
### State ownership hierarchy
|
|
34
|
+
|
|
35
|
+
| Wrapper | Use when |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `@State` | Local, view-owned, value type |
|
|
38
|
+
| `@StateObject` | View-owned reference type (creates once) |
|
|
39
|
+
| `@ObservedObject` | Reference type owned by a parent |
|
|
40
|
+
| `@EnvironmentObject` | Shared across subtree without explicit passing |
|
|
41
|
+
| `@Binding` | Two-way write access into parent state |
|
|
42
|
+
|
|
43
|
+
### Prefer value semantics in models
|
|
44
|
+
|
|
45
|
+
```swift
|
|
46
|
+
struct Item: Identifiable, Hashable {
|
|
47
|
+
let id: UUID
|
|
48
|
+
var title: String
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Avoid `class` for model types unless reference semantics are required.
|
|
53
|
+
|
|
54
|
+
### Navigation
|
|
55
|
+
|
|
56
|
+
Use `NavigationStack` + `navigationDestination(for:)` for type-safe push navigation. Avoid `NavigationView` (deprecated in iOS 16+).
|
|
57
|
+
|
|
58
|
+
```swift
|
|
59
|
+
NavigationStack(path: $router.path) {
|
|
60
|
+
ContentView()
|
|
61
|
+
.navigationDestination(for: Route.self) { route in
|
|
62
|
+
route.view
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Testing
|
|
68
|
+
|
|
69
|
+
### Unit tests
|
|
70
|
+
|
|
71
|
+
Use `XCTest` for synchronous logic and `async` test methods for concurrency:
|
|
72
|
+
|
|
73
|
+
```swift
|
|
74
|
+
func testFetchReturnsItems() async throws {
|
|
75
|
+
let sut = ItemRepository(api: MockAPI())
|
|
76
|
+
let result = try await sut.fetchAll()
|
|
77
|
+
XCTAssertFalse(result.isEmpty)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### UI tests
|
|
82
|
+
|
|
83
|
+
Prefer `XCUITest` for critical flows only — it is slow and flaky. Supplement with snapshot tests (`swift-snapshot-testing`) for visual regression.
|
|
84
|
+
|
|
85
|
+
### Test doubles
|
|
86
|
+
|
|
87
|
+
Declare protocols for dependencies; inject fakes in tests:
|
|
88
|
+
|
|
89
|
+
```swift
|
|
90
|
+
protocol APIClient { func fetch() async throws -> [Item] }
|
|
91
|
+
struct MockAPIClient: APIClient { var stubbedItems: [Item] = [] }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Memory Management
|
|
95
|
+
|
|
96
|
+
- Capture lists in closures: `[weak self]` to break retain cycles
|
|
97
|
+
- Actors do not need `[weak self]` captures for their own methods
|
|
98
|
+
- Use Instruments → Leaks / Allocations to profile before optimizing
|
|
99
|
+
|
|
100
|
+
## Build & Tooling
|
|
101
|
+
|
|
102
|
+
- **Swift Package Manager** for libraries; avoid CocoaPods on new projects
|
|
103
|
+
- **Xcode Cloud** or **Fastlane** for CI
|
|
104
|
+
- Enable `-strict-concurrency=complete` in Swift 5.x projects to prepare for Swift 6
|
|
105
|
+
- `swiftlint` for style; `swiftformat` for formatting
|
|
106
|
+
- Minimum deployment targets: follow current App Store requirements (iOS 16+ as of 2025)
|
|
107
|
+
|
|
108
|
+
## Architecture Patterns
|
|
109
|
+
|
|
110
|
+
### MVVM + Repository
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
View → ViewModel (@MainActor) → Repository (actor) → Network/DB
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- ViewModels hold `@Published` properties; Views observe them
|
|
117
|
+
- Repositories own async data access; isolated with `actor`
|
|
118
|
+
- Business logic lives in domain models, not ViewModels
|
|
119
|
+
|
|
120
|
+
### The Composable Architecture (TCA)
|
|
121
|
+
|
|
122
|
+
Use TCA when state fan-out is complex or testability of reducers is a priority. Adds boilerplate — evaluate against team familiarity.
|
|
123
|
+
|
|
124
|
+
## Common Pitfalls
|
|
125
|
+
|
|
126
|
+
- Do not call `@MainActor` methods from synchronous non-main contexts — use `Task { @MainActor in ... }`
|
|
127
|
+
- Avoid `DispatchQueue.main.async` in new code; use `await MainActor.run { }` instead
|
|
128
|
+
- `@StateObject` vs `@ObservedObject` confusion causes double-initialization bugs — `@StateObject` only at the owner
|
|
129
|
+
- `List` with large datasets: use `lazy` loading or pagination; do not load everything into `@State`
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/development/typescript.md — TypeScript Best Practices — Use this skill when writing, reviewing, or debugging TypeScript or JavaScript co
|
|
3
|
+
|
|
4
|
+
Use this skill when writing, reviewing, or debugging TypeScript or JavaScript code. ## Project Structure
|
|
5
|
+
-->
|
|
6
|
+
# TypeScript Best Practices
|
|
7
|
+
|
|
8
|
+
Use this skill when writing, reviewing, or debugging TypeScript or JavaScript code.
|
|
9
|
+
|
|
10
|
+
## Project Structure
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
src/
|
|
14
|
+
modules/
|
|
15
|
+
users/
|
|
16
|
+
user.service.ts
|
|
17
|
+
user.repository.ts
|
|
18
|
+
user.types.ts
|
|
19
|
+
user.test.ts
|
|
20
|
+
lib/
|
|
21
|
+
validation.ts
|
|
22
|
+
http.ts
|
|
23
|
+
types/
|
|
24
|
+
index.ts
|
|
25
|
+
tsconfig.json
|
|
26
|
+
package.json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- Organize by feature or domain, not by file type
|
|
30
|
+
- Colocate tests with source files or in a parallel `__tests__` directory
|
|
31
|
+
- Barrel exports (`index.ts`) only at module boundaries
|
|
32
|
+
|
|
33
|
+
## Tooling
|
|
34
|
+
|
|
35
|
+
| Tool | Purpose |
|
|
36
|
+
|---|---|
|
|
37
|
+
| TypeScript compiler (tsc) | Type checking |
|
|
38
|
+
| ESLint | Linting |
|
|
39
|
+
| Prettier | Formatting |
|
|
40
|
+
| Vitest / Jest | Testing |
|
|
41
|
+
| tsx / ts-node | Development execution |
|
|
42
|
+
| Biome | All-in-one alternative to ESLint + Prettier |
|
|
43
|
+
|
|
44
|
+
## Type System
|
|
45
|
+
|
|
46
|
+
- Strict mode enabled: `"strict": true` in tsconfig
|
|
47
|
+
- No `any`; use `unknown` when the type is truly unknown, then narrow
|
|
48
|
+
- Prefer interfaces for object shapes; type aliases for unions and intersections
|
|
49
|
+
- Use discriminated unions for state machines and variant types
|
|
50
|
+
- `as const` for literal type inference on arrays and objects
|
|
51
|
+
- Generics with constraints: `<T extends Record<string, unknown>>`
|
|
52
|
+
- Zod or Valibot for runtime validation that infers static types
|
|
53
|
+
|
|
54
|
+
## Error Handling
|
|
55
|
+
|
|
56
|
+
- Use typed error classes extending `Error`
|
|
57
|
+
- `Result<T, E>` pattern (custom or `neverthrow`) for expected failures
|
|
58
|
+
- Try/catch only at boundaries (HTTP handler, message consumer)
|
|
59
|
+
- Always catch async rejections; unhandled rejections crash Node
|
|
60
|
+
- Include context in error messages: what operation, what input
|
|
61
|
+
|
|
62
|
+
## Immutability
|
|
63
|
+
|
|
64
|
+
- `const` by default; `let` only when reassignment is necessary
|
|
65
|
+
- `Readonly<T>` and `ReadonlyArray<T>` for function parameters
|
|
66
|
+
- Spread operator for object and array updates
|
|
67
|
+
- `Object.freeze` for runtime enforcement when needed
|
|
68
|
+
- `as const` for deeply immutable literal types
|
|
69
|
+
|
|
70
|
+
## Patterns
|
|
71
|
+
|
|
72
|
+
### Module Pattern
|
|
73
|
+
- Named exports over default exports (better refactoring, better tree-shaking)
|
|
74
|
+
- Explicit public API via barrel files
|
|
75
|
+
- Internal modules not re-exported
|
|
76
|
+
|
|
77
|
+
### Dependency Injection
|
|
78
|
+
- Constructor injection for services
|
|
79
|
+
- Factory functions for configurable instances
|
|
80
|
+
- Interface-based dependencies for testability
|
|
81
|
+
|
|
82
|
+
### Async Patterns
|
|
83
|
+
- `async/await` over raw promises
|
|
84
|
+
- `Promise.all` for independent concurrent operations
|
|
85
|
+
- `Promise.allSettled` when partial failure is acceptable
|
|
86
|
+
- Set timeouts with `AbortController` on fetch and long operations
|
|
87
|
+
- Never fire-and-forget a promise; handle the result or error
|
|
88
|
+
|
|
89
|
+
## Testing
|
|
90
|
+
|
|
91
|
+
- Vitest or Jest with TypeScript support
|
|
92
|
+
- Mock modules with `vi.mock()` or `jest.mock()`
|
|
93
|
+
- Test behavior, not implementation
|
|
94
|
+
- `@testing-library` for component tests
|
|
95
|
+
- Snapshot tests sparingly; prefer explicit assertions
|
|
96
|
+
- MSW (Mock Service Worker) for HTTP mocking in integration tests
|
|
97
|
+
|
|
98
|
+
## Performance
|
|
99
|
+
|
|
100
|
+
- Lazy imports with `import()` for code splitting
|
|
101
|
+
- Avoid unnecessary object creation in hot paths
|
|
102
|
+
- Use `Map` and `Set` over objects for frequent lookups/additions
|
|
103
|
+
- Profile with Node inspector or Chrome DevTools
|
|
104
|
+
- Monitor event loop lag and memory usage in production
|
|
105
|
+
|
|
106
|
+
## Node.js Specifics
|
|
107
|
+
|
|
108
|
+
- Use `node:` prefix for built-in modules
|
|
109
|
+
- Streams for large data processing
|
|
110
|
+
- Cluster or worker threads for CPU-bound tasks
|
|
111
|
+
- Graceful shutdown: handle SIGTERM, close connections, drain requests
|
|
112
|
+
- Health check endpoint for load balancers
|
|
113
|
+
|
|
114
|
+
## Security
|
|
115
|
+
|
|
116
|
+
- Validate all external input at API boundaries (Zod, Joi, class-validator)
|
|
117
|
+
- Parameterized queries for database access (never string concatenation)
|
|
118
|
+
- `helmet` middleware for HTTP security headers
|
|
119
|
+
- Sanitize user content before HTML rendering
|
|
120
|
+
- Use `crypto.randomUUID()` for identifiers
|
|
121
|
+
- Audit dependencies: `npm audit`, `pnpm audit`
|
|
122
|
+
|
|
123
|
+
## Anti-Patterns
|
|
124
|
+
|
|
125
|
+
- `any` as an escape hatch instead of proper typing
|
|
126
|
+
- Barrel files that re-export everything (kills tree-shaking)
|
|
127
|
+
- Enums for simple unions (prefer string literal unions)
|
|
128
|
+
- Class inheritance chains deeper than two levels
|
|
129
|
+
- Mixing async and sync error handling styles
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/devops/ci-cd.md — CI/CD — Use this skill when designing, debugging, or optimizing CI/CD pipelines.
|
|
3
|
+
|
|
4
|
+
Use this skill when designing, debugging, or optimizing CI/CD pipelines. ## Pipeline Stages
|
|
5
|
+
-->
|
|
6
|
+
# CI/CD
|
|
7
|
+
|
|
8
|
+
Use this skill when designing, debugging, or optimizing CI/CD pipelines.
|
|
9
|
+
|
|
10
|
+
## Pipeline Stages
|
|
11
|
+
|
|
12
|
+
| Stage | Purpose | Tools | Failure Policy |
|
|
13
|
+
|---|---|---|---|
|
|
14
|
+
| Build | Compile, lint, typecheck | tsc, eslint, cargo check, go vet | Fail fast — block all downstream stages |
|
|
15
|
+
| Test | Unit → integration → e2e | Jest, Pytest, go test, Playwright | Fail on any; parallelize within stage |
|
|
16
|
+
| Security Scan | SAST, dep audit, secrets detection | Semgrep, CodeQL, Trivy, gitleaks | Block on CRITICAL/HIGH; warn on MEDIUM |
|
|
17
|
+
| Deploy | Promote artifact through environments | GitHub Actions, ArgoCD, Helm | Gate on all prior stages passing |
|
|
18
|
+
|
|
19
|
+
Always run lint and typecheck before tests — they are faster and catch more errors per second of CI time.
|
|
20
|
+
|
|
21
|
+
## GitHub Actions
|
|
22
|
+
|
|
23
|
+
**Dependency caching:**
|
|
24
|
+
```yaml
|
|
25
|
+
- uses: actions/cache@v4
|
|
26
|
+
with:
|
|
27
|
+
path: ~/.npm
|
|
28
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
29
|
+
restore-keys: ${{ runner.os }}-node-
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use `hashFiles` of the lock file as the cache key. A lock file change invalidates the cache and forces a clean install. Restore keys provide a partial cache hit when the key misses.
|
|
33
|
+
|
|
34
|
+
**Matrix parallelization:**
|
|
35
|
+
```yaml
|
|
36
|
+
strategy:
|
|
37
|
+
matrix:
|
|
38
|
+
node: [18, 20, 22]
|
|
39
|
+
os: [ubuntu-latest, macos-latest]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Sequential job dependencies:**
|
|
43
|
+
```yaml
|
|
44
|
+
jobs:
|
|
45
|
+
build:
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
test:
|
|
48
|
+
needs: build
|
|
49
|
+
deploy:
|
|
50
|
+
needs: [build, test]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Artifact passing between jobs:**
|
|
54
|
+
```yaml
|
|
55
|
+
- uses: actions/upload-artifact@v4
|
|
56
|
+
with:
|
|
57
|
+
name: build-output
|
|
58
|
+
path: dist/
|
|
59
|
+
retention-days: 1
|
|
60
|
+
|
|
61
|
+
- uses: actions/download-artifact@v4
|
|
62
|
+
with:
|
|
63
|
+
name: build-output
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## GitLab CI
|
|
67
|
+
|
|
68
|
+
- `cache: key: $CI_COMMIT_REF_SLUG` with `paths:` for dependency directories.
|
|
69
|
+
- `parallel: matrix:` for version or platform fans.
|
|
70
|
+
- `artifacts: expire_in: 1 day` for build output passed between jobs.
|
|
71
|
+
- `environment: name: staging` for environment tracking and deployment history.
|
|
72
|
+
|
|
73
|
+
## Artifact Management
|
|
74
|
+
|
|
75
|
+
| Artifact Type | Where Stored | Retention | Promotion Gate |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| Build output (JS/CSS) | CI artifact store | 1 day | Tests pass |
|
|
78
|
+
| Container image | Registry (ECR, GCR, GHCR) | 90 days (untagged), permanent (tagged) | Security scan pass |
|
|
79
|
+
| Test reports | CI artifact store | 30 days | N/A |
|
|
80
|
+
| Release binaries | GitHub Releases / S3 | Permanent | Full pipeline pass |
|
|
81
|
+
|
|
82
|
+
## Environment Promotion
|
|
83
|
+
|
|
84
|
+
| Branch | Environment | Gates Required |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| feature/* | None (CI only) | Build + test |
|
|
87
|
+
| main | Staging | Build + test + security scan |
|
|
88
|
+
| main (manual approval) | Production | All staging gates + smoke test + approval |
|
|
89
|
+
| hotfix/* | Production (fast-path) | Build + test + approval |
|
|
90
|
+
|
|
91
|
+
Never auto-deploy to production without a passing security scan and at least one manual approval step.
|
|
92
|
+
|
|
93
|
+
## Secrets in CI
|
|
94
|
+
|
|
95
|
+
- Store secrets in the platform's encrypted secret store (GitHub Actions Secrets, GitLab CI Variables).
|
|
96
|
+
- Never hardcode secrets in workflow files or Dockerfiles.
|
|
97
|
+
- Mask secrets in logs — CI platforms do this automatically for registered secrets; verify it works before relying on it.
|
|
98
|
+
- Rotate any secret immediately after a potential exposure; treat "may have leaked" the same as "did leak".
|
|
99
|
+
- Use OIDC-based short-lived tokens (GitHub OIDC → AWS/GCP/Azure) over long-lived service account keys wherever the cloud provider supports it.
|
|
100
|
+
|
|
101
|
+
## Speed Optimization
|
|
102
|
+
|
|
103
|
+
- Cache dependency layers keyed to lock file hash; a clean install on every run is a CI antipattern.
|
|
104
|
+
- Run lint and typecheck first — they fail fast and cost less than a full test suite.
|
|
105
|
+
- Split slow test suites across workers using matrix or `--shard` flags (Vitest, Jest, Playwright all support sharding).
|
|
106
|
+
- Parallelize independent test files; do not serialize unit tests.
|
|
107
|
+
- In monorepos, run only affected packages: `turbo run test --filter=[HEAD^1]` or `nx affected --target=test`.
|
|
108
|
+
- Set `fail-fast: true` in matrix builds when a single failure is sufficient signal to abort.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/devops/containerization.md — Containerization — Use this skill when writing Dockerfiles, optimizing image size, or securing cont
|
|
3
|
+
|
|
4
|
+
Use this skill when writing Dockerfiles, optimizing image size, or securing container builds. ## Multi-Stage Builds
|
|
5
|
+
-->
|
|
6
|
+
# Containerization
|
|
7
|
+
|
|
8
|
+
Use this skill when writing Dockerfiles, optimizing image size, or securing container builds.
|
|
9
|
+
|
|
10
|
+
## Multi-Stage Builds
|
|
11
|
+
|
|
12
|
+
Use a builder stage to compile and a minimal runtime stage to ship only what is needed:
|
|
13
|
+
|
|
14
|
+
```dockerfile
|
|
15
|
+
FROM node:20 AS builder
|
|
16
|
+
WORKDIR /app
|
|
17
|
+
COPY package*.json ./
|
|
18
|
+
RUN npm ci
|
|
19
|
+
COPY . .
|
|
20
|
+
RUN npm run build
|
|
21
|
+
|
|
22
|
+
FROM node:20-alpine AS runtime
|
|
23
|
+
WORKDIR /app
|
|
24
|
+
COPY --from=builder /app/dist ./dist
|
|
25
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Runtime base image selection:
|
|
29
|
+
- `gcr.io/distroless/nodejs20-debian12` — no shell, no package manager, smallest attack surface for Node.
|
|
30
|
+
- `node:20-alpine` — shell available for debugging; use when distroless breaks scripts.
|
|
31
|
+
- `scratch` — static binaries only (Go, Rust with `musl`).
|
|
32
|
+
- Never use `debian`, `ubuntu`, or `node:20` (Debian-based) as a production runtime base; they carry thousands of unnecessary packages.
|
|
33
|
+
|
|
34
|
+
## Layer Caching
|
|
35
|
+
|
|
36
|
+
Order layers by change frequency — least-changed first:
|
|
37
|
+
|
|
38
|
+
1. Base OS packages (`RUN apk add ...`)
|
|
39
|
+
2. App dependencies (`COPY package*.json ./` then `RUN npm ci`)
|
|
40
|
+
3. Source code (`COPY . .`)
|
|
41
|
+
4. Build output (`RUN npm run build`)
|
|
42
|
+
|
|
43
|
+
Always `COPY package*.json ./` before `COPY . .`. A source change must not invalidate the dependency layer.
|
|
44
|
+
|
|
45
|
+
Use BuildKit mount caches to avoid re-downloading packages across builds:
|
|
46
|
+
```dockerfile
|
|
47
|
+
RUN --mount=type=cache,target=/root/.npm npm ci
|
|
48
|
+
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Combine related `RUN` commands and clean package manager caches in the same layer:
|
|
52
|
+
```dockerfile
|
|
53
|
+
RUN apk add --no-cache curl git && \
|
|
54
|
+
rm -rf /var/cache/apk/*
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Never put cache cleanup in a separate `RUN` — it creates a new layer that does not reclaim space from the previous layer.
|
|
58
|
+
|
|
59
|
+
## Security
|
|
60
|
+
|
|
61
|
+
| Practice | Implementation |
|
|
62
|
+
|---|---|
|
|
63
|
+
| Non-root user | `RUN addgroup -S app && adduser -S app -G app` then `USER app` before CMD |
|
|
64
|
+
| No secrets in layers | Use `--secret` mount at build time or runtime env injection; never `ENV SECRET=` or `ARG TOKEN=` |
|
|
65
|
+
| Minimal base | distroless by default; alpine when a shell is needed; never debian/ubuntu for production |
|
|
66
|
+
| Pinned base digest | `FROM node:20-alpine@sha256:<digest>` prevents silent upstream changes |
|
|
67
|
+
| No `apt-get upgrade` | Pin the base image digest instead; `upgrade` produces non-reproducible layers |
|
|
68
|
+
| Read-only filesystem | Pass `--read-only` at runtime; mount writable tmpfs only for paths that need writes |
|
|
69
|
+
|
|
70
|
+
Never use `ADD` with a URL — it bypasses layer caching in unpredictable ways and cannot be verified. Use `COPY` for local files and `curl` + checksum verification for remote files.
|
|
71
|
+
|
|
72
|
+
## Image Scanning
|
|
73
|
+
|
|
74
|
+
| Tool | Integration | Default Threshold |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| Trivy | `aquasecurity/trivy-action` GitHub Action; `trivy image <name>` CLI | Fail CI on CRITICAL; warn on HIGH |
|
|
77
|
+
| Snyk | `snyk container test <image>`; Snyk Container GitHub Action | Fail on CRITICAL/HIGH; surface fixability data |
|
|
78
|
+
| Docker Scout | `docker scout cves <image>`; built into Docker Desktop | Advisory; set `--exit-code` flag for CI enforcement |
|
|
79
|
+
|
|
80
|
+
Run image scanning in CI after the build stage, before the deploy stage. Scan the exact image SHA that will be deployed, not a rebuilt copy.
|
|
81
|
+
|
|
82
|
+
## .dockerignore
|
|
83
|
+
|
|
84
|
+
Always include a `.dockerignore`. Exclude: `.git`, `node_modules`, `.env`, `*.env`, `test/`, `tests/`, `docs/`, `*.md`, `coverage/`, `*.log`, `dist/` (only if rebuilding inside the container).
|
|
85
|
+
|
|
86
|
+
A missing `.dockerignore` sends the entire repo context to the daemon on every build, including secrets and `.git` history.
|
|
87
|
+
|
|
88
|
+
## Health Checks
|
|
89
|
+
|
|
90
|
+
```dockerfile
|
|
91
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
92
|
+
CMD wget -qO- http://localhost:3000/health || exit 1
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Use an HTTP endpoint for web services. Use a process check (`pgrep`) only for non-HTTP workloads.
|
|
96
|
+
|
|
97
|
+
Kubernetes uses separate liveness, readiness, and startup probes — configure those in the deployment manifest, not in the Dockerfile. The Docker `HEALTHCHECK` is relevant for `docker run` and Docker Compose only.
|
|
98
|
+
|
|
99
|
+
## Size Optimization
|
|
100
|
+
|
|
101
|
+
- Use `dive <image>` to inspect layer sizes and identify waste before shipping.
|
|
102
|
+
- `--no-install-recommends` with `apt-get install` eliminates suggested packages.
|
|
103
|
+
- Always clean package manager caches in the same `RUN` layer as the install command.
|
|
104
|
+
- Use `COPY --chown=app:app` instead of a separate `RUN chown` to avoid a wasted layer.
|
|
105
|
+
- Multi-stage builds remove all build tools, source files, and intermediate artifacts automatically — they are the single highest-impact size reduction technique.
|
|
106
|
+
- For Go and Rust, build a statically linked binary (`CGO_ENABLED=0` for Go, `musl` target for Rust) and copy it into `scratch` or distroless for a final image under 20 MB.
|