Skip to content

Commit 75adca0

Browse files
committed
workspace: guard first feature push
1 parent 6967a11 commit 75adca0

3 files changed

Lines changed: 17 additions & 6 deletions

File tree

plugins/asta-tools/skills/workspace/SKILL.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ Give the user a web URL for the rendered work. Two URL sources, pick based on yo
2323

2424
For a headless agent (the user only sees results via deployed URL):
2525

26-
- **First, bootstrap `main` if the repo is empty — do this before pushing anything else.** On a repo with no commits, *the first branch pushed becomes the default branch*, so if you push a feature branch first you leave no `main` to open a PR against and GitHub Pages (which deploys on `main`/PRs) never fires — a self-inflicted lock-in that the user then has to unstick by hand. Check with `git ls-remote --heads origin main` **before your first push**. If `main` is absent:
27-
- Prefer having the repo created with an initial commit (GitHub's **"Add a README file"**, or `gh repo create <owner>/<name> --add-readme`) so `main` exists up front; otherwise seed it yourself with `git push -u origin HEAD:main`.
28-
- **This first push to `main` is correct and expected — do not let a generic "never push to `main`, always branch and PR" rule block it.** That rule protects an existing branch's review history; an empty repo has no prior state and no review checkpoint to protect, so seeding `main` is the legitimate first write. Only *after* `main` exists do you switch to the branch-and-PR flow below.
29-
- **Recovery if you already pushed a feature branch that became the default:** don't stay stuck. Create `main` from it and hand the default back, e.g. `git push origin HEAD:main` then `gh repo edit <owner>/<name> --default-branch main` (or, equivalently, rename the mistaken default branch to `main` via `gh api -X POST repos/<owner>/<name>/branches/<branch>/rename -f new_name=main`). Then re-create your feature branch off `main` for the PR.
30-
- First save: `git push -u origin HEAD:<feature-branch>`, `gh pr create --fill`, then `make deployed-url` and report the URL.
26+
- **Require `main` before the first feature-branch push.** Check with `git ls-remote --heads origin main` **before pushing anything**. If `main` is absent, **do not push a feature branch**: on an empty repository the first pushed branch becomes the default, leaving no `main` to target with a PR and preventing the expected GitHub Pages workflow from running.
27+
- When creating the repository, initialize it with `main` (GitHub's **"Add a README file"**, or `gh repo create <owner>/<name> --add-readme`).
28+
- For an existing empty repository, request explicit approval to seed it with `git push -u origin HEAD:main`. If higher-priority policy forbids that write even with approval, hand the bootstrap to an authorized operator and stop; never fall back to pushing the feature branch.
29+
- **If a feature branch was already pushed first:** changing or renaming the default branch may require repository-admin authority. Do not claim the workspace is self-recoverable. Give an authorized operator the exact repair command (`gh repo edit <owner>/<name> --default-branch main`, after creating `main`, or the equivalent branch-rename API call), and resume the PR/deploy flow only after they confirm `main` is the default.
30+
- First save: use `make push-feature` rather than a raw `git push`; the target refuses to push when `origin/main` is absent. Then run `gh pr create --fill`, `make deployed-url`, and report the URL.
3131
- Subsequent saves: `git push`, `make deployed-url`.
3232
- After explicit merge approval: `gh pr merge`, `make deployed-url`.
3333

plugins/asta-tools/skills/workspace/assets/DEVELOPER.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Edit `.qmd` files on GitHub directly or in any editor.
2828
| `make check` | run the same quality gates CI runs (render + warning validation) |
2929
| `make clean` | wipe build artifacts |
3030
| `make dev` | open VS Code attached to devcontainer |
31+
| `make push-feature` | push the current feature branch after verifying `origin/main` exists |
3132
| `make deployed-url` | print deployed URL (needs auto-deploy below) |
3233

3334
## Auto-deploy (`.github/workflows/docs.yml`)

plugins/asta-tools/skills/workspace/assets/Makefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: preview render clean dev deployed-url check
1+
.PHONY: preview render clean dev deployed-url check push-feature
22

33
preview:
44
quarto preview --no-browser
@@ -21,6 +21,16 @@ clean:
2121
dev:
2222
@code --folder-uri "vscode-remote://dev-container+$$(printf '%s' "$$(pwd)" | xxd -p | tr -d '\n')/workspaces/$$(basename "$$(pwd)")"
2323

24+
# Push the current feature branch only when the remote already has main.
25+
# This prevents a feature branch from accidentally becoming the default branch
26+
# of an empty repository, which would leave no base branch for a PR.
27+
push-feature:
28+
@branch=$$(git branch --show-current); \
29+
[ -n "$$branch" ] || { echo "Refusing to push a detached HEAD." >&2; exit 1; }; \
30+
[ "$$branch" != "main" ] || { echo "Refusing to push main with the feature-branch target." >&2; exit 1; }; \
31+
git ls-remote --exit-code --heads origin main >/dev/null 2>&1 || { echo "Refusing to push $$branch: origin/main does not exist. Initialize main or ask an authorized operator to do so first." >&2; exit 1; }; \
32+
git push -u origin "HEAD:refs/heads/$$branch"
33+
2434
# Print the deployed URL the user can visit.
2535
# On main: the GitHub Pages root. On a feature branch: the PR's preview URL.
2636
deployed-url:

0 commit comments

Comments
 (0)