Skip to content

ci: deploy bitácora workflows (OPS-002) - #566

Merged
mlorentedev merged 2 commits into
masterfrom
ci/bitacora-workflows
Nov 5, 2026
Merged

mlorentedev merged 2 commits into
masterfrom
ci/bitacora-workflows

Conversation

@mlorentedev

Copy link
Copy Markdown
Owner

Canonical add-to-project.yml + bitacora-status.yml from mlorentedev/dotfiles (runbook §7). Deployed via scripts/bitacora-rollout.sh — this repo's default branch is protected, so the rollout lands through a PR.

@coderabbitai

coderabbitai Bot commented Nov 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 31 seconds.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d569fa9f-bcbf-4332-af86-00fef22e535f
Commits

Reviewing files that changed from the base of the PR and between 0e6730e and 08d4a2b.

Files selected for processing: 2

  • .github/workflows/add-to-project.yml
  • .github/workflows/bitacora-status.yml
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 08d4a2b)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Retry warning corrupts project id

REAL - gh_graphql writes its retry diagnostic to stdout (the ::warning::transient failure ... printf has no >&2), but the first caller captures the function's stdout: PROJECT_ID=$(gh_graphql -f query=... --jq ...). If the project lookup hits one transient error (5xx/EOF/timeout are all matched patterns) and the retry then succeeds, PROJECT_ID contains ::warning::transient failure (attempt 1/3), retrying followed by the node id. It passes the non-empty check and is sent as the project GraphQL variable, so the mutation fails with "Could not resolve to a node with the global id of ..." and the job goes red — the retry path the header promises converts a recovered transient error into a hard failure. Route function diagnostics to stderr (or write the response to a separate fd/temp file) so command substitution sees only the response.

printf '::warning::transient failure (attempt %d/%d), retrying\n' "$attempt" "$max"
sleep $(( attempt * 5 ))
attempt=$(( attempt + 1 ))
Dead null-project guard

REAL - The guard [ -n "${PROJECT_ID}" ] with the message "project id resolved empty with no API error" cannot fire for the case it names. gh api --jq '.data.user.projectV2.id' prints the literal string null when the path resolves to null (project #1 deleted or renamed, or projectV2 absent), which is non-empty, so the check passes and the mutation is sent with project="null", failing with an unrelated "Could not resolve to a node with the global id of 'null'" and the generic fatal message instead of the intended diagnostic. Compare against null explicitly or filter it: --jq '.data.user.projectV2.id // empty' (or [ -n "${PROJECT_ID}" ] && [ "${PROJECT_ID}" != "null" ]).

PROJECT_ID=$(gh_graphql -f query='
  query { user(login: "mlorentedev") { projectV2(number: 1) { id } } }
' --jq '.data.user.projectV2.id') || rc=$?

if [ "$rc" -eq 0 ] && [ -n "${PROJECT_ID}" ]; then
  # $project and $contentId are GraphQL variables, not shell ones.
  # shellcheck disable=SC2016
  gh_graphql -f query='
    mutation($project: ID!, $contentId: ID!) {
      addProjectV2ItemById(input: {projectId: $project, contentId: $contentId}) {
        item { id }
      }
    }
  ' -f project="$PROJECT_ID" -f contentId="$CONTENT_NODE_ID" >/dev/null || rc=$?
elif [ "$rc" -eq 0 ]; then
  printf '::error::project id resolved empty with no API error\n'
  rc=1
fi
Classification trusts exit code

THEORETICAL - The three-way classification (rate limit / transient / fatal) keys entirely on gh api graphql's exit status. GitHub's GraphQL endpoint returns {"errors":[{"type":"RATE_LIMITED",...}]} and many validation/permission errors with HTTP 200, and gh api exits 0 on a 200 body, so gh_graphql would take the success branch: on the --jq call the error body is discarded and .data.user.projectV2.id becomes null; on the mutation call the body is discarded by >/dev/null, so the script prints ::notice::added to the bitácora board and exits green although nothing was added — the same silent drop the header exists to stop, and the RATE_LIMITED soft-fail branch at the end would be unreachable for its main case. Add an explicit errors check on the response (e.g. --jq 'if .errors then ... else ... end') rather than relying solely on exit status. Uncertainty: this depends on whether the gh version resolved on the runner surfaces GraphQL errors as a non-zero exit; I could not execute gh api graphql here to confirm.

if out=$(gh api graphql "$@" 2>&1); then
  printf '%s' "$out"
  return 0
fi

⚙️ Agent run details
  • Model: openai/mimo-v2.6-flash
  • Tokens: 11,089 in / 7,887 out / 18,976 total
  • Time cost: 160.3s
  • AI calls: 1

@mlorentedev

Copy link
Copy Markdown
Owner Author

Review triage

Reviewers: PR-Agent (on 08d4a2b, 3 focus areas). CodeRabbit did not review: free limit reached, so this PR has no CodeRabbit review. The PR deploys dotfiles' canonical copies, so every finding is disposed there, in mlorentedev/dotfiles#3160. The triage was done by the author of the rollout fixes.

Finding Disposition
Retry notice on stdout corrupts PROJECT_ID after a recovered transient error (REAL) Ticketed, #3160 item 10, marked first to fix
null project id passes the non-empty guard (REAL) Ticketed, item 11
Classification trusts gh api's exit code while GraphQL errors arrive as HTTP 200 (THEORETICAL) Ticketed, item 12

All checks green. The bug in item 10 is already live on main in every repository that merged the rollout, so merging this PR does not add exposure. Holding the PR until #3160 lands would also be reasonable.

@mlorentedev
mlorentedev merged commit 4bc5684 into master Nov 5, 2026
13 checks passed
@mlorentedev
mlorentedev deleted the ci/bitacora-workflows branch November 5, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant