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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/agent-shield-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ jobs:
continue
fi

if ! echo "$frontmatter" | grep -q '^name:'; then
# Allow optional leading whitespace so indented YAML keys
# (e.g. under a `metadata:` parent) are recognised.
if ! echo "$frontmatter" | grep -qE '^[[:space:]]*name:'; then
echo "::error file=$file::Missing 'name' field"
status=1
fi
if ! echo "$frontmatter" | grep -q '^description:'; then
if ! echo "$frontmatter" | grep -qE '^[[:space:]]*description:'; then
echo "::error file=$file::Missing 'description' field"
status=1
fi
Expand Down
25 changes: 17 additions & 8 deletions .github/workflows/dependabot-rebase-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,29 @@ jobs:
continue
fi

# Check if all required checks pass (look at overall rollup)
CHECKS_PASS=$(gh pr view "$PR_NUMBER" --repo "$REPO" \
--json statusCheckRollup \
--jq '[.statusCheckRollup[]? | select(.name != null and .status == "COMPLETED") | .conclusion] | all(. == "SUCCESS" or . == "NEUTRAL" or . == "SKIPPED")')

CHECKS_PENDING=$(gh pr view "$PR_NUMBER" --repo "$REPO" \
--json statusCheckRollup \
--jq '[.statusCheckRollup[]? | select(.name != null and .status != "COMPLETED")] | length')
# Check the status check rollup. We need:
# - at least one completed check (so an empty rollup is NOT
# vacuously "passing"), and
# - every completed check is SUCCESS / NEUTRAL / SKIPPED, and
# - zero checks still pending.
ROLLUP=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json statusCheckRollup)
CHECKS_COMPLETED=$(echo "$ROLLUP" | \
jq '[.statusCheckRollup[]? | select(.name != null and .status == "COMPLETED")] | length')
CHECKS_PASS=$(echo "$ROLLUP" | \
jq '[.statusCheckRollup[]? | select(.name != null and .status == "COMPLETED") | .conclusion] | all(. == "SUCCESS" or . == "NEUTRAL" or . == "SKIPPED")')
CHECKS_PENDING=$(echo "$ROLLUP" | \
jq '[.statusCheckRollup[]? | select(.name != null and .status != "COMPLETED")] | length')

if [[ "$CHECKS_PENDING" -gt 0 ]]; then
echo " Skipping — $CHECKS_PENDING check(s) still pending"
continue
fi

if [[ "$CHECKS_COMPLETED" -eq 0 ]]; then
echo " Skipping — no completed status checks (cannot confirm safety)"
continue
fi

if [[ "$CHECKS_PASS" != "true" ]]; then
echo " Skipping — some checks failed"
continue
Expand Down
57 changes: 51 additions & 6 deletions .github/workflows/dependency-audit-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,57 @@ jobs:

- name: Audit Cargo dependencies
run: |
# cargo audit operates on Cargo.lock at workspace root
# For workspaces, a single audit at root covers all crates
# cargo audit operates on Cargo.lock at workspace root, so for a
# workspace a single audit at the root covers every member crate.
# Iterating every Cargo.toml would re-audit the same lockfile N
# times in workspaces.
#
# Strategy:
# 1. Find every Cargo.toml that declares [workspace] — those
# are workspace roots; emit them.
# 2. Find every Cargo.toml that does NOT declare [workspace];
# those are either standalone crates or workspace members.
# Emit them only if no parent dir is already a workspace
# root we found in step 1.
status=0
while IFS= read -r dir; do

mapfile -t WORKSPACES < <(
find . -name Cargo.toml -not -path '*/target/*' -print0 \
| xargs -0 grep -l '^\[workspace\]' 2>/dev/null \
| xargs -n1 dirname 2>/dev/null \
| sort -u
)

mapfile -t NON_WORKSPACES < <(
find . -name Cargo.toml -not -path '*/target/*' -print0 \
| xargs -0 grep -L '^\[workspace\]' 2>/dev/null \
| xargs -n1 dirname 2>/dev/null \
| sort -u
Comment on lines +180 to +191
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workspace discovery pipelines convert NUL-delimited find -print0 output into newline/whitespace-delimited paths before dirname (via grep then xargs -n1 dirname). That will mis-handle Cargo.toml paths containing spaces/tabs/newlines. Consider keeping NUL delimiters end-to-end (e.g., grep -Z + xargs -0) or using find ... -exec sh -c ... to emit workspace/dir names without whitespace splitting.

Suggested change
mapfile -t WORKSPACES < <(
find . -name Cargo.toml -not -path '*/target/*' -print0 \
| xargs -0 grep -l '^\[workspace\]' 2>/dev/null \
| xargs -n1 dirname 2>/dev/null \
| sort -u
)
mapfile -t NON_WORKSPACES < <(
find . -name Cargo.toml -not -path '*/target/*' -print0 \
| xargs -0 grep -L '^\[workspace\]' 2>/dev/null \
| xargs -n1 dirname 2>/dev/null \
| sort -u
mapfile -d '' -t WORKSPACES < <(
find . -name Cargo.toml -not -path '*/target/*' -print0 \
| xargs -0 grep -Z -l '^\[workspace\]' 2>/dev/null \
| xargs -0 -n1 dirname -z 2>/dev/null \
| sort -zu
)
mapfile -d '' -t NON_WORKSPACES < <(
find . -name Cargo.toml -not -path '*/target/*' -print0 \
| xargs -0 grep -Z -L '^\[workspace\]' 2>/dev/null \
| xargs -0 -n1 dirname -z 2>/dev/null \
| sort -zu

Copilot uses AI. Check for mistakes.
)

# Standalone crates: those whose dir is not under any workspace root
STANDALONE=()
for dir in "${NON_WORKSPACES[@]}"; do
covered=0
for ws in "${WORKSPACES[@]}"; do
# Trim trailing slash from $ws for accurate prefix match
ws_trim="${ws%/}"
case "$dir/" in
"$ws_trim/"*) covered=1; break ;;
esac
done
if [ "$covered" -eq 0 ]; then
STANDALONE+=("$dir")
fi
done

for dir in "${WORKSPACES[@]}" "${STANDALONE[@]}"; do
echo "::group::cargo audit $dir"
if ! (cd "$dir" && cargo generate-lockfile 2>/dev/null; cargo audit); then
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the cargo audit subshell, cargo audit is separated by ; so it will run even if cd "$dir" fails (and also regardless of cargo generate-lockfile success). This can cause auditing the wrong directory. Chain commands so cargo audit only runs after a successful cd (and decide whether a lockfile generation failure should be fatal or explicitly ignored).

Suggested change
if ! (cd "$dir" && cargo generate-lockfile 2>/dev/null; cargo audit); then
if ! (cd "$dir" && { cargo generate-lockfile 2>/dev/null || true; } && cargo audit); then

Copilot uses AI. Check for mistakes.
status=1
fi
echo "::endgroup::"
done < <(find . -name 'Cargo.toml' -not -path '*/target/*' -exec dirname {} \; | sort -u)
done
exit $status

audit-pip:
Expand All @@ -193,14 +234,18 @@ jobs:
- name: Audit Python dependencies
run: |
status=0
# Audit each Python project found in the repo
# Audit each Python project found in the repo. Some projects ship
# both pyproject.toml (tooling/build) and requirements.txt (pinned
# runtime deps) — audit BOTH when both are present rather than
# short-circuiting on pyproject.toml.
while IFS= read -r dir; do
echo "::group::pip-audit $dir"
if [ -f "$dir/pyproject.toml" ]; then
if ! pip-audit "$dir"; then
status=1
fi
elif [ -f "$dir/requirements.txt" ]; then
fi
if [ -f "$dir/requirements.txt" ]; then
if ! pip-audit -r "$dir/requirements.txt"; then
status=1
fi
Expand Down
2 changes: 1 addition & 1 deletion standards/workflows/feature-ideation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ name: Feature Research & Ideation (BMAD Analyst)

on:
schedule:
- cron: '0 7 * * 5' # Friday 07:00 UTC (3 AM EDT / 2 AM EST)
- cron: '0 7 * * 5' # Friday 07:00 UTC (3 AM EDT / 2 AM EST)
workflow_dispatch:
inputs:
focus_area:
Expand Down
Loading