chore: add workflow files to git tracking

This commit is contained in:
DhanushSantosh
2026-01-14 00:54:46 +05:30
parent fa3ead0e8d
commit 520d9a945c
3 changed files with 468 additions and 2 deletions

2
.gitignore vendored
View File

@@ -90,8 +90,6 @@ pnpm-lock.yaml
yarn.lock
# Fork-specific workflow files (should never be committed)
DEVELOPMENT_WORKFLOW.md
check-sync.sh
# API key files
data/.api-key
data/credentials.json

253
DEVELOPMENT_WORKFLOW.md Normal file
View File

@@ -0,0 +1,253 @@
# Development Workflow
This document defines the standard workflow for keeping a branch in sync with the upstream
release candidate (RC) and for shipping feature work. It is paired with `check-sync.sh`.
## Quick Decision Rule
1. Ask the user to select a workflow:
- **Sync Workflow** → you are maintaining the current RC branch with fixes/improvements
and will push the same fixes to both origin and upstream RC when you have local
commits to publish.
- **PR Workflow** → you are starting new feature work on a new branch; upstream updates
happen via PR only.
2. After the user selects, run:
```bash
./check-sync.sh
```
3. Use the status output to confirm alignment. If it reports **diverged**, default to
merging `upstream/<TARGET_RC>` into the current branch and preserving local commits.
For Sync Workflow, when the working tree is clean and you are behind upstream RC,
proceed with the fetch + merge without asking for additional confirmation.
## Target RC Resolution
The target RC is resolved dynamically so the workflow stays current as the RC changes.
Resolution order:
1. Latest `upstream/v*rc` branch (auto-detected)
2. `upstream/HEAD` (fallback)
3. If neither is available, you must pass `--rc <branch>`
Override for a single run:
```bash
./check-sync.sh --rc <rc-branch>
```
## Pre-Flight Checklist
1. Confirm a clean working tree:
```bash
git status
```
2. Confirm the current branch:
```bash
git branch --show-current
```
3. Ensure remotes exist (origin + upstream):
```bash
git remote -v
```
## Sync Workflow (Upstream Sync)
Use this flow when you are updating the current branch with fixes or improvements and
intend to keep origin and upstream RC in lockstep.
1. **Check sync status**
```bash
./check-sync.sh
```
2. **Update from upstream RC before editing (no pulls)**
- **Behind upstream RC** → fetch and merge RC into your branch:
```bash
git fetch upstream
git merge upstream/<TARGET_RC> --no-edit
```
When the working tree is clean and the user selected Sync Workflow, proceed without
an extra confirmation prompt.
- **Diverged** → stop and resolve manually.
3. **Resolve conflicts if needed**
- Handle conflicts intelligently: preserve upstream behavior and your local intent.
4. **Make changes and commit (if you are delivering fixes)**
```bash
git add -A
git commit -m "type: description"
```
5. **Build to verify**
```bash
npm run build:packages
npm run build
```
6. **Push after a successful merge to keep remotes aligned**
- If you only merged upstream RC changes, push **origin only** to sync your fork:
```bash
git push origin <branch>
```
- If you have local fixes to publish, push **origin + upstream**:
```bash
git push origin <branch>
git push upstream <branch>:<TARGET_RC>
```
- Always ask the user which push to perform.
- Origin (origin-only sync):
```bash
git push origin <branch>
```
- Upstream RC (publish the same fixes when you have local commits):
```bash
git push upstream <branch>:<TARGET_RC>
```
7. **Re-check sync**
```bash
./check-sync.sh
```
## PR Workflow (Feature Work)
Use this flow only for new feature work on a new branch. Do not push to upstream RC.
1. **Create or switch to a feature branch**
```bash
git checkout -b <branch>
```
2. **Make changes and commit**
```bash
git add -A
git commit -m "type: description"
```
3. **Merge upstream RC before shipping**
```bash
git merge upstream/<TARGET_RC> --no-edit
```
4. **Build and/or test**
```bash
npm run build:packages
npm run build
```
5. **Push to origin**
```bash
git push -u origin <branch>
```
6. **Create or update the PR**
- Use `gh pr create` or the GitHub UI.
7. **Review and follow-up**
- Apply feedback, commit changes, and push again.
- Re-run `./check-sync.sh` if additional upstream sync is needed.
## Conflict Resolution Checklist
1. Identify which changes are from upstream vs. local.
2. Preserve both behaviors where possible; avoid dropping either side.
3. Prefer minimal, safe integrations over refactors.
4. Re-run build commands after resolving conflicts.
5. Re-run `./check-sync.sh` to confirm status.
## Build/Test Matrix
- **Sync Workflow**: `npm run build:packages` and `npm run build`.
- **PR Workflow**: `npm run build:packages` and `npm run build` (plus relevant tests).
## Post-Sync Verification
1. `git status` should be clean.
2. `./check-sync.sh` should show expected alignment.
3. Verify recent commits with:
```bash
git log --oneline -5
```
## check-sync.sh Usage
- Uses dynamic Target RC resolution (see above).
- Override target RC:
```bash
./check-sync.sh --rc <rc-branch>
```
- Optional preview limit:
```bash
./check-sync.sh --preview 10
```
- The script prints sync status for both origin and upstream and previews recent commits
when you are behind.
## Stop Conditions
Stop and ask for guidance if any of the following are true:
- The working tree is dirty and you are about to merge or push.
- `./check-sync.sh` reports **diverged** during PR Workflow, or a merge cannot be completed.
- The script cannot resolve a target RC and requests `--rc`.
- A build fails after sync or conflict resolution.
## AI Agent Guardrails
- Always run `./check-sync.sh` before merges or pushes.
- Always ask for explicit user approval before any push command.
- Do not ask for additional confirmation before a Sync Workflow fetch + merge when the
working tree is clean and the user has already selected the Sync Workflow.
- Choose Sync vs PR workflow based on intent (RC maintenance vs new feature work), not
on the script's workflow hint.
- Only use force push when the user explicitly requests a history rewrite.
- Ask for explicit approval before dependency installs, branch deletion, or destructive operations.
- When resolving merge conflicts, preserve both upstream changes and local intent where possible.
- Do not create or switch to new branches unless the user explicitly requests it.
## AI Agent Decision Guidance
Agents should provide concrete, task-specific suggestions instead of repeatedly asking
open-ended questions. Use the user's stated goal and the `./check-sync.sh` status to
propose a default path plus one or two alternatives, and only ask for confirmation when
an action requires explicit approval.
Default behavior:
- If the intent is RC maintenance, recommend the Sync Workflow and proceed with
safe preparation steps (status checks, previews). If the branch is behind upstream RC,
fetch and merge without additional confirmation when the working tree is clean, then
push to origin to keep the fork aligned. Push upstream only when there are local fixes
to publish.
- If the intent is new feature work, recommend the PR Workflow and proceed with safe
preparation steps (status checks, identifying scope). Ask for approval before merges,
pushes, or dependency installs.
- If `./check-sync.sh` reports **diverged** during Sync Workflow, merge
`upstream/<TARGET_RC>` into the current branch and preserve local commits.
- If `./check-sync.sh` reports **diverged** during PR Workflow, stop and ask for guidance
with a short explanation of the divergence and the minimal options to resolve it.
If the user's intent is RC maintenance, prefer the Sync Workflow regardless of the
script hint. When the intent is new feature work, use the PR Workflow and avoid upstream
RC pushes.
Suggestion format (keep it short):
- **Recommended**: one sentence with the default path and why it fits the task.
- **Alternatives**: one or two options with the tradeoff or prerequisite.
- **Approval points**: mention any upcoming actions that need explicit approval (exclude sync
workflow pushes and merges).
## Failure Modes and How to Avoid Them
Sync Workflow:
- Wrong RC target: verify the auto-detected RC in `./check-sync.sh` output before merging.
- Diverged from upstream RC: stop and resolve manually before any merge or push.
- Dirty working tree: commit or stash before syncing to avoid accidental merges.
- Missing remotes: ensure both `origin` and `upstream` are configured before syncing.
- Build breaks after sync: run `npm run build:packages` and `npm run build` before pushing.
PR Workflow:
- Branch not synced to current RC: re-run `./check-sync.sh` and merge RC before shipping.
- Pushing the wrong branch: confirm `git branch --show-current` before pushing.
- Unreviewed changes: always commit and push to origin before opening or updating a PR.
- Skipped tests/builds: run the build commands before declaring the PR ready.
## Notes
- Avoid merging with uncommitted changes; commit or stash first.
- Prefer merge over rebase for PR branches; rebases rewrite history and often require a force push,
which should only be done with an explicit user request.
- Use clear, conventional commit messages and split unrelated changes into separate commits.

215
check-sync.sh Executable file
View File

@@ -0,0 +1,215 @@
#!/usr/bin/env bash
set -euo pipefail
DEFAULT_RC_PATTERN="v*rc"
DEFAULT_PREVIEW_COUNT=5
PREVIEW_COUNT="${PREVIEW_COUNT:-$DEFAULT_PREVIEW_COUNT}"
CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
ORIGIN_REF="origin/${CURRENT_BRANCH}"
TARGET_RC_SOURCE="auto"
print_header() {
echo "=== Sync Status Check ==="
echo
printf "Target RC: %s (%s)\n" "$TARGET_RC" "$TARGET_RC_SOURCE"
echo
}
ensure_git_repo() {
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "Not inside a git repository."
exit 1
fi
}
ensure_remote() {
local remote="$1"
if ! git remote get-url "$remote" >/dev/null 2>&1; then
echo "Remote '$remote' is not configured."
exit 1
fi
}
fetch_remote() {
local remote="$1"
git fetch --quiet "$remote"
}
warn_if_dirty() {
if [[ -n "$(git status --porcelain)" ]]; then
echo "Warning: working tree has uncommitted changes."
echo
fi
}
resolve_target_rc() {
if [[ -n "${TARGET_RC:-}" ]]; then
return
fi
local rc_candidates
rc_candidates="$(git for-each-ref --format='%(refname:short)' "refs/remotes/upstream/${DEFAULT_RC_PATTERN}" || true)"
if [[ -n "$rc_candidates" ]]; then
TARGET_RC="$(printf "%s\n" "$rc_candidates" | sed 's|^upstream/||' | sort -V | tail -n 1)"
TARGET_RC_SOURCE="auto:latest"
return
fi
local upstream_head
upstream_head="$(git symbolic-ref --quiet --short refs/remotes/upstream/HEAD 2>/dev/null || true)"
if [[ -n "$upstream_head" ]]; then
TARGET_RC="${upstream_head#upstream/}"
TARGET_RC_SOURCE="auto:upstream-head"
return
fi
echo "Unable to resolve target RC automatically. Use --rc <branch>."
exit 1
}
ref_exists() {
local ref="$1"
git show-ref --verify --quiet "refs/remotes/${ref}"
}
print_status_line() {
local label="$1"
local behind="$2"
local ahead="$3"
if [[ "$behind" -eq 0 && "$ahead" -eq 0 ]]; then
printf "✅ %s: in sync (behind %s, ahead %s)\n" "$label" "$behind" "$ahead"
elif [[ "$behind" -eq 0 ]]; then
printf "⬆️ %s: ahead %s (behind %s)\n" "$label" "$ahead" "$behind"
elif [[ "$ahead" -eq 0 ]]; then
printf "⬇️ %s: behind %s (ahead %s)\n" "$label" "$behind" "$ahead"
else
printf "⚠️ %s: %s behind, %s ahead (diverged)\n" "$label" "$behind" "$ahead"
fi
}
print_preview() {
local title="$1"
local range="$2"
echo
echo "$title"
git log --oneline -n "$PREVIEW_COUNT" "$range"
}
print_branch_context() {
echo "Branch: $CURRENT_BRANCH"
echo "Upstream RC: $UPSTREAM_REF"
echo "Upstream push: enabled for sync workflow"
echo
}
print_upstream_summary() {
local behind="$1"
local ahead="$2"
if [[ "$behind" -eq 0 && "$ahead" -eq 0 ]]; then
echo "Branch vs upstream RC: in sync (behind $behind, ahead $ahead)"
else
echo "Branch vs upstream RC: behind $behind, ahead $ahead"
fi
}
print_workflow_hint() {
local behind="$1"
local ahead="$2"
if [[ "$behind" -eq 0 && "$ahead" -eq 0 ]]; then
echo "Workflow: sync"
elif [[ "$behind" -gt 0 && "$ahead" -eq 0 ]]; then
echo "Workflow: sync (merge upstream RC)"
elif [[ "$ahead" -gt 0 && "$behind" -eq 0 ]]; then
echo "Workflow: pr (local work not in upstream)"
else
echo "Workflow: diverged (resolve manually)"
fi
}
print_usage() {
echo "Usage: ./check-sync.sh [--rc <branch>] [--preview <count>]"
}
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--rc)
shift
if [[ -z "${1-}" ]]; then
echo "Missing value for --rc"
exit 1
fi
TARGET_RC="$1"
TARGET_RC_SOURCE="flag"
;;
--preview)
shift
if [[ -z "${1-}" ]]; then
echo "Missing value for --preview"
exit 1
fi
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
echo "Invalid preview count: $1"
exit 1
fi
PREVIEW_COUNT="$1"
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "Unknown argument: $1"
print_usage
exit 1
;;
esac
shift
done
}
ensure_git_repo
ensure_remote origin
ensure_remote upstream
parse_args "$@"
fetch_remote origin
fetch_remote upstream
resolve_target_rc
UPSTREAM_REF="upstream/${TARGET_RC}"
print_header
warn_if_dirty
print_branch_context
if ! ref_exists "$ORIGIN_REF"; then
echo "Origin branch '$ORIGIN_REF' does not exist."
else
read -r origin_behind origin_ahead < <(git rev-list --left-right --count "$ORIGIN_REF...HEAD")
print_status_line "Origin" "$origin_behind" "$origin_ahead"
fi
if ! ref_exists "$UPSTREAM_REF"; then
echo "Upstream ref '$UPSTREAM_REF' does not exist."
else
read -r upstream_behind upstream_ahead < <(git rev-list --left-right --count "$UPSTREAM_REF...HEAD")
print_status_line "Upstream" "$upstream_behind" "$upstream_ahead"
echo
print_upstream_summary "$upstream_behind" "$upstream_ahead"
print_workflow_hint "$upstream_behind" "$upstream_ahead"
if [[ "$upstream_behind" -gt 0 ]]; then
print_preview "Recent upstream commits:" "HEAD..$UPSTREAM_REF"
fi
if [[ "$upstream_ahead" -gt 0 ]]; then
print_preview "Commits on this branch not in upstream:" "$UPSTREAM_REF..HEAD"
fi
fi