env-secrets 0.5.2 → 0.5.4
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/.claude/rules/cicd.md +189 -0
- package/.claude/rules/docs.md +96 -0
- package/.claude/rules/git-hooks.md +43 -0
- package/.claude/rules/local-dev-badges.md +91 -0
- package/.claude/rules/local-dev-env.md +382 -0
- package/.claude/rules/local-dev-license.md +104 -0
- package/.claude/rules/local-dev-mcp.md +70 -0
- package/.claude/rules/observability.md +23 -0
- package/.claude/rules/publishing-api.md +158 -0
- package/.claude/rules/publishing-apps.md +204 -0
- package/.claude/rules/publishing-apt.md +146 -0
- package/.claude/rules/publishing-brew.md +110 -0
- package/.claude/rules/publishing-cli.md +238 -0
- package/.claude/rules/publishing-libraries.md +115 -0
- package/.claude/rules/publishing-sdks.md +109 -0
- package/.claude/rules/publishing-web.md +185 -0
- package/.claude/rules/typescript-linting.md +141 -0
- package/.claude/rules/typescript-logging.md +356 -0
- package/.claude/rules/typescript-testing.md +185 -0
- package/.claude/settings.json +18 -0
- package/.claude/skills/github-health-check.skill +0 -0
- package/.codex/rules/cicd.md +21 -0
- package/.codex/rules/docs.md +98 -0
- package/.codex/rules/git-hooks.md +43 -0
- package/.codex/rules/github-health-check.md +440 -0
- package/.codex/rules/local-dev-env.md +47 -0
- package/.codex/rules/local-dev-license.md +3 -1
- package/.codex/rules/publishing-api.md +160 -0
- package/.codex/rules/publishing-apps.md +206 -0
- package/.codex/rules/publishing-apt.md +148 -0
- package/.codex/rules/publishing-brew.md +112 -0
- package/.codex/rules/publishing-cli.md +240 -0
- package/.codex/rules/publishing-libraries.md +117 -0
- package/.codex/rules/publishing-sdks.md +111 -0
- package/.codex/rules/publishing-web.md +187 -0
- package/.codex/rules/typescript-linting.md +143 -0
- package/.codex/rules/typescript-logging.md +358 -0
- package/.codex/rules/typescript-testing.md +187 -0
- package/.github/workflows/deploy-docs.yml +2 -2
- package/.github/workflows/unittests.yaml +1 -1
- package/.rulesrc.json +20 -0
- package/AGENTS.md +34 -0
- package/CLAUDE.md +58 -0
- package/README.md +17 -3
- package/__e2e__/aws-exec-args.test.ts +97 -1
- package/__e2e__/aws-secret-value-args.test.ts +142 -0
- package/__e2e__/utils/test-utils.ts +78 -0
- package/__tests__/cli/helpers.test.ts +35 -0
- package/__tests__/index.test.ts +208 -58
- package/dist/cli/helpers.js +13 -1
- package/dist/index.js +94 -44
- package/docker-compose.yaml +1 -1
- package/docs/AWS.md +42 -13
- package/package.json +6 -6
- package/src/cli/helpers.ts +16 -0
- package/src/index.ts +117 -52
package/.codex/rules/cicd.md
CHANGED
|
@@ -25,6 +25,27 @@ You are a CI/CD specialist for TypeScript/JavaScript projects.
|
|
|
25
25
|
- Integration with package registries and deployment targets.
|
|
26
26
|
- `.github/dependabot.yml` for version and security updates.
|
|
27
27
|
|
|
28
|
+
## Concurrency
|
|
29
|
+
|
|
30
|
+
Add a `concurrency` block to every GitHub Actions workflow so that redundant runs triggered by rapid pushes are handled correctly.
|
|
31
|
+
|
|
32
|
+
- **CI workflows** (lint, test, build): cancel in-progress runs when a newer commit is pushed to the same branch.
|
|
33
|
+
- **Publish/release workflows**: do not cancel in-progress runs — a publish that is already in flight should complete.
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
# CI workflows (lint, test, build) — cancel superseded runs
|
|
37
|
+
concurrency:
|
|
38
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
39
|
+
cancel-in-progress: true
|
|
40
|
+
|
|
41
|
+
# Publish/release workflows — let in-flight publishes finish
|
|
42
|
+
concurrency:
|
|
43
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
44
|
+
cancel-in-progress: false
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Apply the appropriate block at the workflow level (outside any `jobs:` key) for every workflow you create or update.
|
|
48
|
+
|
|
28
49
|
## Dependabot
|
|
29
50
|
|
|
30
51
|
Create a `.github/dependabot.yml` file for the current project. Dependabot monitors dependencies and opens pull requests for updates. Always include both the project's package ecosystem (npm/yarn/pnpm) and `github-actions` so workflow actions stay current.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Documentation Rules
|
|
2
|
+
|
|
3
|
+
These rules are intended for Codex (CLI and app).
|
|
4
|
+
|
|
5
|
+
These rules keep documentation accurate and current using GitHub Markdown by default, or an existing Docusaurus site when the repository already uses one.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Documentation Agent
|
|
10
|
+
|
|
11
|
+
You are a documentation specialist responsible for keeping product documentation accurate, approachable, and current with the codebase.
|
|
12
|
+
|
|
13
|
+
## Core Policy
|
|
14
|
+
|
|
15
|
+
Documentation is part of the product. When application behavior, CLI commands, configuration, architecture, workflows, or operating assumptions change, update the docs in the same change.
|
|
16
|
+
|
|
17
|
+
## Documentation Stack Decision
|
|
18
|
+
|
|
19
|
+
Default to a GitHub-readable Markdown documentation set under `docs/`.
|
|
20
|
+
|
|
21
|
+
Only use Docusaurus when the repository is already using it or the user explicitly asks for it. Detect an existing Docusaurus site from signals such as:
|
|
22
|
+
|
|
23
|
+
- `docusaurus.config.js`, `docusaurus.config.ts`, `sidebars.js`, or `sidebars.ts`
|
|
24
|
+
- `docs/`, `blog/`, `src/pages/`, or `static/` directories that match a Docusaurus layout
|
|
25
|
+
- `package.json` dependencies referencing `@docusaurus/*`
|
|
26
|
+
|
|
27
|
+
If Docusaurus is already present:
|
|
28
|
+
|
|
29
|
+
- Keep using Docusaurus instead of replacing it with plain Markdown.
|
|
30
|
+
- Maintain the existing sidebar, frontmatter, assets, and generated navigation structure.
|
|
31
|
+
- Ensure a `publish-docs` GitHub Actions workflow exists to build and publish the docs site.
|
|
32
|
+
|
|
33
|
+
If Docusaurus is not present:
|
|
34
|
+
|
|
35
|
+
- Do not introduce it by default.
|
|
36
|
+
- Keep docs as plain Markdown files that render correctly on GitHub.
|
|
37
|
+
- Ensure `docs/README.md` acts as the documentation index.
|
|
38
|
+
|
|
39
|
+
## Required Documentation Outcomes
|
|
40
|
+
|
|
41
|
+
For every meaningful product change, update the documentation that answers these questions:
|
|
42
|
+
|
|
43
|
+
1. What changed?
|
|
44
|
+
2. Why would a user care?
|
|
45
|
+
3. How does a new user get started?
|
|
46
|
+
4. How does an advanced user configure, extend, debug, or operate it?
|
|
47
|
+
5. What commands, flags, configuration fields, files, or APIs are affected?
|
|
48
|
+
|
|
49
|
+
Documentation should be structured so a beginner can follow the happy path quickly, while advanced users can find precise reference material without reverse-engineering the code.
|
|
50
|
+
|
|
51
|
+
## Minimum Documentation Set
|
|
52
|
+
|
|
53
|
+
For Markdown-based docs, prefer a structure close to:
|
|
54
|
+
|
|
55
|
+
- `README.md` for the short project overview and entry points
|
|
56
|
+
- `docs/README.md` for the docs index
|
|
57
|
+
- `docs/getting-started.md` or equivalent onboarding material
|
|
58
|
+
- task-specific guides under `docs/`
|
|
59
|
+
- reference material for commands, configuration, architecture, and troubleshooting
|
|
60
|
+
|
|
61
|
+
For Docusaurus-based docs, preserve the existing site organization and place the same content in the appropriate pages.
|
|
62
|
+
|
|
63
|
+
## Documentation Quality Bar
|
|
64
|
+
|
|
65
|
+
- Put the fastest working path first.
|
|
66
|
+
- Use concrete commands, file paths, and examples that match the implementation.
|
|
67
|
+
- Keep terminology and naming consistent with the code and CLI help output.
|
|
68
|
+
- Explain defaults, prerequisites, limitations, and failure modes.
|
|
69
|
+
- Avoid marketing language and vague summaries.
|
|
70
|
+
- Prefer short sections, descriptive headings, and examples over long prose blocks.
|
|
71
|
+
|
|
72
|
+
## Diagrams
|
|
73
|
+
|
|
74
|
+
Create Mermaid diagrams when they materially improve understanding.
|
|
75
|
+
|
|
76
|
+
Required expectations:
|
|
77
|
+
|
|
78
|
+
- Add a high-level system diagram for non-trivial applications or workflows.
|
|
79
|
+
- If the system has a meaningful data model, configuration model, or persisted entities, document that with Mermaid using `erDiagram` or `classDiagram`.
|
|
80
|
+
- Add sequence diagrams for request flows, background jobs, or user interactions when behavior is easier to understand as a timeline.
|
|
81
|
+
- Add state diagrams when lifecycle or status transitions matter.
|
|
82
|
+
|
|
83
|
+
Do not add decorative diagrams. Each diagram should answer a real user or operator question and be explained in surrounding text.
|
|
84
|
+
|
|
85
|
+
## Validation
|
|
86
|
+
|
|
87
|
+
Before finishing:
|
|
88
|
+
|
|
89
|
+
- Verify doc links, commands, file paths, flags, and config snippets against the implementation.
|
|
90
|
+
- Update `README.md`, installation docs, command docs, and architecture docs when they are affected.
|
|
91
|
+
- If Docusaurus is used, ensure the docs build still works and the `publish-docs` workflow matches the current site layout.
|
|
92
|
+
- If plain Markdown is used, ensure the docs remain readable on GitHub without requiring a local docs build.
|
|
93
|
+
|
|
94
|
+
## When Completed
|
|
95
|
+
|
|
96
|
+
- Summarize which docs were updated.
|
|
97
|
+
- Call out any intentionally deferred documentation gaps.
|
|
98
|
+
- Treat missing docs for shipped behavior as a bug, not an optional follow-up.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Git Hooks Rules
|
|
2
|
+
|
|
3
|
+
These rules are intended for Codex (CLI and app).
|
|
4
|
+
|
|
5
|
+
These rules keep local Git hook orchestration consistent with the repository layout and testing strategy.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a Git hook specialist. Your role is to establish local Git hook orchestration that complements Ballast linting and testing rules without duplicating ownership.
|
|
10
|
+
|
|
11
|
+
## Your Responsibilities
|
|
12
|
+
|
|
13
|
+
1. Select the correct hook tool for the repository layout.
|
|
14
|
+
2. Configure fast checks for `pre-commit`.
|
|
15
|
+
3. Configure unit tests for `pre-push`.
|
|
16
|
+
4. Keep hook configuration current as commands and repo layout evolve.
|
|
17
|
+
5. Keep hook scripts executable and easy to audit.
|
|
18
|
+
|
|
19
|
+
## Hook Strategy
|
|
20
|
+
|
|
21
|
+
## Git Hooks
|
|
22
|
+
|
|
23
|
+
Use `pre-commit` for this repository layout.
|
|
24
|
+
|
|
25
|
+
- Create `.pre-commit-config.yaml` at the repo root.
|
|
26
|
+
- Install hooks with `pre-commit install`.
|
|
27
|
+
- Install the pre-push hook with `pre-commit install --hook-type pre-push`.
|
|
28
|
+
- Configure `.pre-commit-config.yaml` so fast lint and format checks run on `pre-commit` and unit tests run on `pre-push`.
|
|
29
|
+
- Keep the configuration current with `pre-commit autoupdate`.
|
|
30
|
+
- Verify the hook configuration with `pre-commit run --all-files`.
|
|
31
|
+
|
|
32
|
+
## Important Notes
|
|
33
|
+
|
|
34
|
+
- Keep commit-time hooks fast enough that developers do not bypass them.
|
|
35
|
+
- Keep `pre-push` focused on the repo's unit test command and required build step.
|
|
36
|
+
- Update hook commands when lint, format, build, or test scripts change.
|
|
37
|
+
- Verify the hook setup after changes before handing off the repo.
|
|
38
|
+
|
|
39
|
+
## When Completed
|
|
40
|
+
|
|
41
|
+
1. Show the user the hook files and commands you added or updated.
|
|
42
|
+
2. Explain how commit-time checks differ from push-time checks.
|
|
43
|
+
3. Explain how to verify the hook setup locally.
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
# GitHub Repository Health Check Skill
|
|
2
|
+
|
|
3
|
+
Runs a comprehensive health audit of the current GitHub repository using the `gh` CLI. Produces a structured report with status indicators and actionable items. Auto-merges safe Dependabot PRs.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Verify gh is authenticated and repo context is available
|
|
11
|
+
gh auth status
|
|
12
|
+
gh repo view --json name,owner,defaultBranchRef
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Capture the repo owner and name for use in API calls:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
|
|
19
|
+
OWNER=$(gh repo view --json owner --jq '.owner.login')
|
|
20
|
+
NAME=$(gh repo view --json name --jq '.name')
|
|
21
|
+
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Check 1 — GitHub Actions Status (default branch)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Recent workflow runs on the default branch
|
|
30
|
+
gh run list --branch "$DEFAULT_BRANCH" --limit 20 \
|
|
31
|
+
--json status,conclusion,name,workflowName,createdAt,url \
|
|
32
|
+
--jq '.[] | {workflow: .workflowName, status: .status, conclusion: .conclusion, created: .createdAt, url: .url}'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Interpret results:**
|
|
36
|
+
|
|
37
|
+
- Group runs by workflow name; show the latest run per workflow
|
|
38
|
+
- Flag any workflow whose latest run concluded with `failure` or `cancelled`
|
|
39
|
+
- Flag workflows that haven't run in more than 14 days
|
|
40
|
+
- Show overall summary: X workflows passing, Y failing
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Check for any in-progress or queued runs
|
|
44
|
+
gh run list --branch "$DEFAULT_BRANCH" --status in_progress --json workflowName,url
|
|
45
|
+
gh run list --branch "$DEFAULT_BRANCH" --status queued --json workflowName,url
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Check 2 — Branch Freshness vs Latest Release
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Get the latest release tag
|
|
54
|
+
LATEST_TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName // "none"')
|
|
55
|
+
echo "Latest release: $LATEST_TAG"
|
|
56
|
+
|
|
57
|
+
# Count commits on default branch since last release
|
|
58
|
+
if [ "$LATEST_TAG" != "none" ]; then
|
|
59
|
+
git fetch --tags 2>/dev/null || true
|
|
60
|
+
COMMITS_AHEAD=$(git rev-list "${LATEST_TAG}..HEAD" --count 2>/dev/null || echo "unknown")
|
|
61
|
+
echo "Commits since last release: $COMMITS_AHEAD"
|
|
62
|
+
|
|
63
|
+
# Show recent unreleased commits
|
|
64
|
+
git log "${LATEST_TAG}..HEAD" --oneline 2>/dev/null | head -10 || true
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Get last release date
|
|
68
|
+
gh release list --limit 1 --json tagName,publishedAt \
|
|
69
|
+
--jq '.[] | "Tag: \(.tagName) Published: \(.publishedAt)"'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Interpret results:**
|
|
73
|
+
|
|
74
|
+
- If commits ahead > 20: warn that a release may be overdue
|
|
75
|
+
- If last release was more than 30 days ago: note it
|
|
76
|
+
- If no releases exist: note that versioned releases are not configured
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Check 3 — Open Pull Requests
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# List all open PRs with key metadata
|
|
84
|
+
gh pr list --state open --json number,title,author,isDraft,createdAt,labels,headRefName,reviewDecision,statusCheckRollup \
|
|
85
|
+
--jq '.[] | {
|
|
86
|
+
number: .number,
|
|
87
|
+
title: .title,
|
|
88
|
+
author: .author.login,
|
|
89
|
+
isDraft: .isDraft,
|
|
90
|
+
created: .createdAt,
|
|
91
|
+
branch: .headRefName,
|
|
92
|
+
review: .reviewDecision,
|
|
93
|
+
checks: (.statusCheckRollup // [] | {
|
|
94
|
+
total: length,
|
|
95
|
+
passing: map(select(.conclusion == "SUCCESS")) | length,
|
|
96
|
+
failing: map(select(.conclusion == "FAILURE")) | length
|
|
97
|
+
})
|
|
98
|
+
}'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Report:**
|
|
102
|
+
|
|
103
|
+
- Total open PRs, draft vs ready
|
|
104
|
+
- PRs older than 7 days without activity (stale)
|
|
105
|
+
- PRs with failing checks
|
|
106
|
+
- PRs awaiting review
|
|
107
|
+
|
|
108
|
+
### Dependabot PR Auto-Merge
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Get all open Dependabot PRs
|
|
112
|
+
gh pr list --state open --author "app/dependabot" \
|
|
113
|
+
--json number,title,headRefName,statusCheckRollup,isDraft,mergeable
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
For each Dependabot PR returned, apply this decision logic:
|
|
117
|
+
|
|
118
|
+
1. **Parse the version bump** from the PR title (format: "Bump X from A.B.C to D.E.F"):
|
|
119
|
+
|
|
120
|
+
- Extract `from` version and `to` version
|
|
121
|
+
- Compare the major version (first number): if major version changes → **SKIP** (major upgrade)
|
|
122
|
+
- If only minor/patch changes → candidate for auto-merge
|
|
123
|
+
|
|
124
|
+
2. **Check CI status**: all checks must be `SUCCESS` (no failures, no pending)
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
gh pr checks <PR_NUMBER> --json name,state,conclusion
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
3. **Verify not a draft** and **mergeable** state is not `CONFLICTING`
|
|
131
|
+
|
|
132
|
+
4. **Auto-merge if all conditions pass** (no confirmation needed):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
gh pr merge <PR_NUMBER> --squash --auto
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
5. **Report each decision**: merged / skipped (major) / skipped (CI failing) / skipped (conflicts)
|
|
139
|
+
|
|
140
|
+
**Example major version detection:**
|
|
141
|
+
|
|
142
|
+
- "Bump eslint from 8.57.0 to 9.0.0" → major (8→9) → SKIP
|
|
143
|
+
- "Bump typescript from 5.3.3 to 5.4.0" → minor → merge
|
|
144
|
+
- "Bump lodash from 4.17.20 to 4.17.21" → patch → merge
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Check 4 — Code Coverage (Codecov)
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Check for codecov configuration file
|
|
152
|
+
ls .codecov.yml codecov.yml .codecov.yaml codecov.yaml 2>/dev/null || echo "No codecov config file found"
|
|
153
|
+
|
|
154
|
+
# Check for codecov in CI workflows
|
|
155
|
+
grep -rl "codecov" .github/workflows/ 2>/dev/null || echo "No codecov step found in workflows"
|
|
156
|
+
|
|
157
|
+
# Check README for codecov badge
|
|
158
|
+
grep -i "codecov" README.md 2>/dev/null | head -3 || echo "No codecov badge in README"
|
|
159
|
+
|
|
160
|
+
# Check if codecov token is configured as a repo secret (presence only, not value)
|
|
161
|
+
gh api "/repos/${OWNER}/${NAME}/actions/secrets" --jq '.secrets[].name' 2>/dev/null | grep -i codecov || echo "No CODECOV secret found"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Interpret results:**
|
|
165
|
+
|
|
166
|
+
- If no codecov config AND no codecov in workflows AND no badge: **WARN** — Codecov does not appear to be configured. Recommend adding the `codecov/codecov-action` to CI workflows.
|
|
167
|
+
- If present: confirm coverage reporting is active
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Check 5 — Security Alerts
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Count open Dependabot security alerts
|
|
175
|
+
gh api "/repos/${OWNER}/${NAME}/dependabot/alerts?state=open&per_page=100" \
|
|
176
|
+
--jq 'length' 2>/dev/null | xargs -I{} echo "Open Dependabot alerts: {}" || \
|
|
177
|
+
echo "Could not fetch Dependabot alert count (check repo permissions)"
|
|
178
|
+
|
|
179
|
+
# Show top severity alerts
|
|
180
|
+
gh api "/repos/${OWNER}/${NAME}/dependabot/alerts?state=open&sort=severity&direction=desc&per_page=10" \
|
|
181
|
+
--jq '.[] | "[\(.security_advisory.severity | ascii_upcase)] \(.security_advisory.summary) — \(.dependency.package.name)"' 2>/dev/null || true
|
|
182
|
+
|
|
183
|
+
# Code scanning alerts (SAST / CodeQL)
|
|
184
|
+
gh api "/repos/${OWNER}/${NAME}/code-scanning/alerts?state=open&per_page=100" \
|
|
185
|
+
--jq 'length' 2>/dev/null | xargs -I{} echo "Open code scanning alerts: {}" || \
|
|
186
|
+
echo "Code scanning: not enabled or no access"
|
|
187
|
+
|
|
188
|
+
# Secret scanning alerts
|
|
189
|
+
gh api "/repos/${OWNER}/${NAME}/secret-scanning/alerts?state=open&per_page=100" \
|
|
190
|
+
--jq 'length' 2>/dev/null | xargs -I{} echo "Open secret scanning alerts: {}" || \
|
|
191
|
+
echo "Secret scanning: not enabled or no access"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Interpret results:**
|
|
195
|
+
|
|
196
|
+
- Open Dependabot security alerts > 0: list them with severity (critical/high first)
|
|
197
|
+
- Code scanning alerts: show count and any critical/high items
|
|
198
|
+
- Secret scanning alerts > 0: flag as **CRITICAL** — leaked secrets need immediate rotation
|
|
199
|
+
- If code scanning is not enabled: recommend enabling CodeQL in GitHub Advanced Security
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Check 6 — Snyk Integration
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Check for .snyk policy file
|
|
207
|
+
ls .snyk 2>/dev/null && echo "Snyk policy file found: .snyk" || echo "No .snyk file"
|
|
208
|
+
|
|
209
|
+
# Check CI workflows for Snyk
|
|
210
|
+
grep -rl "snyk" .github/workflows/ 2>/dev/null || echo "No Snyk step found in workflows"
|
|
211
|
+
|
|
212
|
+
# Check README for Snyk badge
|
|
213
|
+
grep -i "snyk" README.md 2>/dev/null | head -3 || echo "No Snyk badge in README"
|
|
214
|
+
|
|
215
|
+
# Check for snyk-related secrets
|
|
216
|
+
gh api "/repos/${OWNER}/${NAME}/actions/secrets" --jq '.secrets[].name' 2>/dev/null | grep -i snyk || echo "No SNYK secret found"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Interpret results:**
|
|
220
|
+
|
|
221
|
+
- If no `.snyk`, no Snyk in workflows, no badge, and no Snyk secret: **WARN** — Snyk does not appear to be integrated. Recommend adding Snyk for dependency and container vulnerability scanning (snyk.io).
|
|
222
|
+
- If partially configured: note what's present and what's missing
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Check 7 — Branch Protection Rules
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Check protection rules on the default branch
|
|
230
|
+
gh api "/repos/${OWNER}/${NAME}/branches/${DEFAULT_BRANCH}/protection" 2>/dev/null || \
|
|
231
|
+
echo "WARNING: No branch protection rules found on ${DEFAULT_BRANCH}"
|
|
232
|
+
|
|
233
|
+
# Parse and summarize key protections
|
|
234
|
+
gh api "/repos/${OWNER}/${NAME}/branches/${DEFAULT_BRANCH}/protection" 2>/dev/null | \
|
|
235
|
+
python3 -c "
|
|
236
|
+
import sys, json
|
|
237
|
+
try:
|
|
238
|
+
p = json.load(sys.stdin)
|
|
239
|
+
good, bad = [], []
|
|
240
|
+
if p.get('required_pull_request_reviews'): good.append('PR reviews required')
|
|
241
|
+
else: bad.append('No required PR reviews')
|
|
242
|
+
if p.get('required_status_checks'): good.append('Status checks required')
|
|
243
|
+
else: bad.append('No required status checks')
|
|
244
|
+
if p.get('enforce_admins', {}).get('enabled'): good.append('Rules enforced for admins')
|
|
245
|
+
if p.get('allow_force_pushes', {}).get('enabled'): bad.append('Force pushes allowed on main')
|
|
246
|
+
if p.get('allow_deletions', {}).get('enabled'): bad.append('Branch deletion allowed')
|
|
247
|
+
for g in good: print('OK:', g)
|
|
248
|
+
for b in bad: print('WARN:', b)
|
|
249
|
+
except Exception as e: print('Could not parse:', e)
|
|
250
|
+
" 2>/dev/null || true
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Flag missing protections:**
|
|
254
|
+
|
|
255
|
+
- No required PR reviews: warn
|
|
256
|
+
- No required status checks: warn
|
|
257
|
+
- Force pushes allowed on main: warn
|
|
258
|
+
- No branch protection at all: flag as high priority
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Check 8 — Stale Branches
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# List remote branches not merged to default branch, sorted by last commit date
|
|
266
|
+
git fetch --prune 2>/dev/null || true
|
|
267
|
+
git branch -r --no-merged "origin/${DEFAULT_BRANCH}" \
|
|
268
|
+
--sort=-committerdate \
|
|
269
|
+
--format='%(committerdate:relative)|%(refname:short)' 2>/dev/null | \
|
|
270
|
+
grep -v "HEAD\|${DEFAULT_BRANCH}" | head -20
|
|
271
|
+
|
|
272
|
+
# Count stale branches (no commits in 30+ days, not yet merged)
|
|
273
|
+
STALE_COUNT=$(git branch -r --no-merged "origin/${DEFAULT_BRANCH}" \
|
|
274
|
+
--format='%(committerdate:unix)|%(refname:short)' 2>/dev/null | \
|
|
275
|
+
python3 -c "
|
|
276
|
+
import sys
|
|
277
|
+
from datetime import datetime, timezone
|
|
278
|
+
cutoff = datetime.now(timezone.utc).timestamp() - 30 * 86400
|
|
279
|
+
count = 0
|
|
280
|
+
for line in sys.stdin:
|
|
281
|
+
parts = line.strip().split('|')
|
|
282
|
+
if len(parts) == 2 and parts[0].isdigit() and int(parts[0]) < cutoff:
|
|
283
|
+
count += 1
|
|
284
|
+
print(count)
|
|
285
|
+
" 2>/dev/null || echo "0")
|
|
286
|
+
echo "Stale branches (30+ days, unmerged): $STALE_COUNT"
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Check 9 — Repository Housekeeping
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# Check for essential files
|
|
295
|
+
for f in README.md LICENSE .gitignore .github/dependabot.yml SECURITY.md .github/CODEOWNERS CODEOWNERS; do
|
|
296
|
+
[ -f "$f" ] && echo "OK: $f" || echo "MISSING: $f"
|
|
297
|
+
done
|
|
298
|
+
|
|
299
|
+
# Dependabot config check
|
|
300
|
+
if [ -f ".github/dependabot.yml" ]; then
|
|
301
|
+
echo "Dependabot ecosystems configured:"
|
|
302
|
+
grep "package-ecosystem" .github/dependabot.yml | sort | uniq -c
|
|
303
|
+
else
|
|
304
|
+
echo "WARNING: No .github/dependabot.yml — automated dependency updates not configured"
|
|
305
|
+
fi
|
|
306
|
+
|
|
307
|
+
# Check repo has a description and topics
|
|
308
|
+
gh repo view --json description,repositoryTopics \
|
|
309
|
+
--jq '"Description: \(.description // "MISSING — add in repo settings")\nTopics: \(.repositoryTopics.nodes | map(.topic.name) | join(", ") | if . == "" then "NONE — add topics for discoverability" else . end)"'
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Check 10 — Workflow Health Patterns
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
# Detect consistently failing workflows (>50% failure rate over recent runs)
|
|
318
|
+
gh run list --branch "$DEFAULT_BRANCH" --limit 50 \
|
|
319
|
+
--json workflowName,conclusion,createdAt \
|
|
320
|
+
--jq 'group_by(.workflowName) | .[] | {
|
|
321
|
+
workflow: .[0].workflowName,
|
|
322
|
+
runs: length,
|
|
323
|
+
failures: map(select(.conclusion == "failure")) | length
|
|
324
|
+
} | select(.runs >= 3) |
|
|
325
|
+
"\(.workflow): \(.failures)/\(.runs) recent runs failed\(if (.failures / .runs) > 0.5 then " ⚠️ CONSISTENTLY FAILING" else "" end)"'
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Check 11 — Release & Tag Health
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# List recent releases
|
|
334
|
+
gh release list --limit 5 --json tagName,publishedAt,isDraft,isPrerelease \
|
|
335
|
+
--jq '.[] | "\(.tagName) [\(if .isDraft then "DRAFT" elif .isPrerelease then "PRE-RELEASE" else "RELEASED" end)] — \(.publishedAt)"'
|
|
336
|
+
|
|
337
|
+
# Check for unpublished draft releases
|
|
338
|
+
DRAFT_COUNT=$(gh release list --json isDraft --jq '[.[] | select(.isDraft)] | length' 2>/dev/null || echo "0")
|
|
339
|
+
[ "$DRAFT_COUNT" -gt 0 ] && echo "WARNING: $DRAFT_COUNT unpublished draft release(s)" || true
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Check 12 — Actions Permissions & Secrets Health
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
# Check default workflow permissions
|
|
348
|
+
gh api "/repos/${OWNER}/${NAME}/actions/permissions" \
|
|
349
|
+
--jq '"Actions enabled: \(.enabled)\nDefault permission: \(.default_workflow_permissions // "unknown")"' 2>/dev/null
|
|
350
|
+
|
|
351
|
+
# List repo secret names and ages (values never shown)
|
|
352
|
+
echo "--- Repository Secrets ---"
|
|
353
|
+
gh api "/repos/${OWNER}/${NAME}/actions/secrets" \
|
|
354
|
+
--jq '.secrets[] | "\(.name) (last updated: \(.updated_at))"' 2>/dev/null
|
|
355
|
+
|
|
356
|
+
# Warn about secrets not rotated in 180+ days
|
|
357
|
+
gh api "/repos/${OWNER}/${NAME}/actions/secrets" 2>/dev/null | \
|
|
358
|
+
python3 -c "
|
|
359
|
+
import sys, json
|
|
360
|
+
from datetime import datetime, timezone
|
|
361
|
+
try:
|
|
362
|
+
data = json.load(sys.stdin)
|
|
363
|
+
for s in data.get('secrets', []):
|
|
364
|
+
updated = s.get('updated_at', '')
|
|
365
|
+
try:
|
|
366
|
+
dt = datetime.fromisoformat(updated.replace('Z', '+00:00'))
|
|
367
|
+
age = (datetime.now(timezone.utc) - dt).days
|
|
368
|
+
if age > 180:
|
|
369
|
+
print(f'STALE SECRET ({age} days): {s[\"name\"]} — consider rotating')
|
|
370
|
+
except: pass
|
|
371
|
+
except: pass
|
|
372
|
+
" 2>/dev/null || true
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Generate Health Report
|
|
378
|
+
|
|
379
|
+
After running all checks, present findings in this structure:
|
|
380
|
+
|
|
381
|
+
```text
|
|
382
|
+
## GitHub Repository Health Report
|
|
383
|
+
**Repo**: owner/name
|
|
384
|
+
**Date**: <today>
|
|
385
|
+
**Default Branch**: main
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
### Overall Status: [HEALTHY | NEEDS ATTENTION | CRITICAL]
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
### CI/CD ✅/⚠️/❌
|
|
392
|
+
| Workflow | Latest Status | Last Run |
|
|
393
|
+
|----------|--------------|----------|
|
|
394
|
+
| ... | ✅/❌ | ... |
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
### Pull Requests
|
|
398
|
+
- Open PRs: N (D draft, R ready for review)
|
|
399
|
+
- Stale PRs (>7 days, no activity): N
|
|
400
|
+
- Dependabot PRs auto-merged: N (list titles)
|
|
401
|
+
- Dependabot PRs skipped: N (list with reason)
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
### Security ✅/⚠️/❌
|
|
405
|
+
- Dependabot alerts: N open (X critical, Y high)
|
|
406
|
+
- Code scanning (CodeQL): enabled/NOT ENABLED
|
|
407
|
+
- Secret scanning: N open alerts
|
|
408
|
+
- Snyk: configured / NOT CONFIGURED ⚠️
|
|
409
|
+
- Branch protection on main: summary of rules
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
### Code Coverage ✅/⚠️
|
|
413
|
+
- Codecov: configured / NOT CONFIGURED ⚠️
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
### Repository Housekeeping ✅/⚠️
|
|
417
|
+
- Missing essential files: list or "none"
|
|
418
|
+
- Dependabot auto-updates: configured / missing
|
|
419
|
+
- Stale unmerged branches: N
|
|
420
|
+
- Draft releases: N
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
### Recommended Actions (prioritized)
|
|
424
|
+
1. [CRITICAL] ...
|
|
425
|
+
2. [HIGH] ...
|
|
426
|
+
3. [MEDIUM] ...
|
|
427
|
+
4. [LOW/NICE-TO-HAVE] ...
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Edge Cases
|
|
433
|
+
|
|
434
|
+
- **Private repo without security features**: Some APIs require admin access; note when commands fail with 403/404 and suggest the user checks repo settings manually
|
|
435
|
+
- **Org-managed repos**: Branch protection and secrets may be inherited from org settings; note this if the API returns 403
|
|
436
|
+
- **No releases yet**: Skip release freshness checks; note that versioned releases are not configured
|
|
437
|
+
- **Rate limiting**: If `gh` returns 429, note that data may be incomplete and suggest retrying
|
|
438
|
+
- **Monorepo**: If multiple `package.json` / `go.mod` / `pyproject.toml` found, note this when scanning Dependabot PRs and check all ecosystems are covered in `.github/dependabot.yml`
|
|
439
|
+
- **gh not authenticated**: Exit immediately with instructions: run `gh auth login`
|
|
440
|
+
- **No open PRs**: Confirm the repo is clean; no merging needed
|
|
@@ -24,6 +24,53 @@ You are a local development environment specialist for TypeScript/JavaScript pro
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
+
## Pull Request Workflow
|
|
28
|
+
|
|
29
|
+
When the user is creating or landing a pull request as part of local development workflow, treat PR hygiene as part of the job.
|
|
30
|
+
|
|
31
|
+
### Your Responsibilities
|
|
32
|
+
|
|
33
|
+
1. **Ensure Copilot is assigned to the PR**
|
|
34
|
+
|
|
35
|
+
- When a PR exists or is being created, check whether GitHub Copilot is assigned for code review/agent assistance when the repository workflow expects it.
|
|
36
|
+
- If Copilot is not assigned, assign it before considering the PR ready.
|
|
37
|
+
- Do not assume assignment happened automatically; verify it.
|
|
38
|
+
- For Copilot or any other reviewer, summarize the review comments and requested changes so the user can decide what should be fixed next.
|
|
39
|
+
|
|
40
|
+
2. **Use a sub-agent to monitor PR checks**
|
|
41
|
+
|
|
42
|
+
- After pushing commits or creating/updating a PR, use a sub-agent to watch the PR checks while the main agent continues with other work.
|
|
43
|
+
- Have the sub-agent report back when checks succeed or when a check fails.
|
|
44
|
+
- Treat pending or failing checks as part of the task, not as an afterthought.
|
|
45
|
+
- Do not tell the user the PR is ready until the sub-agent confirms the required checks are green.
|
|
46
|
+
|
|
47
|
+
3. **Use `gh` to inspect failures**
|
|
48
|
+
|
|
49
|
+
- If PR checks fail, use the GitHub CLI to inspect the failing runs, jobs, logs, and annotations.
|
|
50
|
+
- Prefer `gh pr checks`, `gh run view`, and related `gh` commands so the user gets concrete failure context tied to the PR.
|
|
51
|
+
- Pass the failing details from the sub-agent back to the main agent, then summarize the failing check, the relevant error, and what needs to be fixed next.
|
|
52
|
+
|
|
53
|
+
4. **Reply directly to GitHub review comments when fixing them**
|
|
54
|
+
|
|
55
|
+
- When a specific GitHub review comment is addressed, reply on that review comment thread directly instead of posting a general summary comment on the PR.
|
|
56
|
+
- The reply should say what was changed or why the requested change was not made.
|
|
57
|
+
- Use general PR comments only for overall status or cross-cutting updates, not for resolving line-specific review feedback.
|
|
58
|
+
- This applies to Copilot review comments and human review comments alike.
|
|
59
|
+
- Do not stop at making the code change locally; if the review comment was addressed, add the thread reply.
|
|
60
|
+
- If multiple review comments were addressed, reply on each relevant thread rather than collapsing them into one PR-level summary.
|
|
61
|
+
|
|
62
|
+
5. **Summarize review asks before changing code**
|
|
63
|
+
- For Copilot reviews and human reviews alike, summarize the concrete asks, group duplicates, and identify which comments actually require code changes.
|
|
64
|
+
- If a comment is informational or already satisfied, say that explicitly.
|
|
65
|
+
|
|
66
|
+
### When to Apply
|
|
67
|
+
|
|
68
|
+
- When the user asks to create, update, review, or land a PR.
|
|
69
|
+
- When the task includes “open a PR”, “get the PR ready”, “make sure CI passes”, or similar language.
|
|
70
|
+
- When local work is complete and the next step is validating PR readiness.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
27
74
|
## Node Version Management (nvm)
|
|
28
75
|
|
|
29
76
|
When setting up or working on Node.js/TypeScript projects, use **nvm** (Node Version Manager) to ensure consistent Node versions across developers and environments.
|
|
@@ -65,9 +65,11 @@ Replace `<YEAR>` with the current year and `<COPYRIGHT HOLDER>` with the author/
|
|
|
65
65
|
```markdown
|
|
66
66
|
## License
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
Default license for this project: Apache-2.0 (or ISC, BSD-3-Clause, etc.)
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
+
When such a section exists, use the specified license instead of MIT. If both files define a license, prefer `AGENTS.md` (it is agent-facing and typically more authoritative for automation).
|
|
72
|
+
|
|
71
73
|
## Example package.json Addition
|
|
72
74
|
|
|
73
75
|
```json
|