chore: improve tooling quality and docs

- close_issue.sh: add set -euo pipefail, argument validation, confirmation output
- mark_issue.sh: track previously untracked claim/release script
- create_pr.sh: remove hardcoded one-off (use create_pr.py instead)
- README.md: reflect current toolset with usage examples
- .gitignore: ignore venv/ and __pycache__/
This commit is contained in:
2026-06-21 17:11:44 -04:00
parent d3659534ef
commit 7404f768d3
5 changed files with 104 additions and 29 deletions
+3
View File
@@ -0,0 +1,3 @@
venv/
__pycache__/
*.pyc
+35 -11
View File
@@ -2,23 +2,47 @@
A collection of Python and Bash scripts to automate interactions with Gitea instances.
## Setup
## Supported Instances
A Python virtual environment is included. Activate it using:
```bash
source venv/bin/activate
```
| Remote | Host | Org / Repo |
|----------------|----------------------------|-------------------------------------|
| `dadeschools` | `gitea.dadeschools.net` | `Contractor / Timesheet` |
| `prgs` | `gitea.prgs.cc` | `Scaled-Tech-Consulting / Timesheet`|
## Authentication
These scripts securely extract tokens from the macOS keychain to avoid hardcoding secrets.
- **Dade Schools (gitea.dadeschools.net)**: Retrieved via `git credential fill`. Ensure you have logged in via Git over HTTPS at least once so the keychain caches your credentials.
- **NetBridge / Personal (gitea.prgs.cc)**: Retrieved using `security find-generic-password` for the service `netbridge-gitea-token`.
Credentials are retrieved via `git credential fill` for the target host. Ensure you have
logged in via Git over HTTPS at least once so the keychain caches your credentials.
## Available Scripts
- `./create_issue.py` - Create an issue in the Gitea tracker
- `./create_pr.py` - Open a Pull Request from a branch via the API
- `./create_pr.sh` - Bash equivalent for creating a PR via the API
- `./close_issue.sh` - Close a specific issue via the API
| Script | Description |
|---------------------|-----------------------------------------------------|
| `create_issue.py` | Create an issue (`--remote`, `--title`, `--body`) |
| `create_pr.py` | Open a Pull Request (`--remote`, `--title`, `--head`, `--base`) |
| `close_issue.sh` | Close a specific issue (dadeschools only) |
| `mark_issue.sh` | Claim/release an issue via `status:in-progress` label |
| `manage_labels.py` | Create label set and apply label mappings (`--dry` to preview) |
### Quick Examples
```bash
# Create an issue
./create_issue.py --title "Fix PDF output" --body "Blank on Safari"
# Create a PR
./create_pr.py --title "feat: add validation" --head feat/validation --body "Closes #12"
# Close issue #5
./close_issue.sh 5
# Claim an issue before working on it
./mark_issue.sh 10 start
# Release when done
./mark_issue.sh 10 done
```
Use `--help` on any Python script for full usage details.
+16 -4
View File
@@ -1,15 +1,27 @@
#!/usr/bin/env bash
# Close a Gitea issue by setting its state to "closed".
#
# Usage: ./close_issue.sh <issue_number>
#
# Auth: macOS keychain via `git credential fill` (same as the other scripts).
set -euo pipefail
HOST="gitea.dadeschools.net"
API="https://$HOST/api/v1"
ORG="Contractor"
REPO="Timesheet"
ISSUE_NUM=$1
ISSUE_NUM="${1:?usage: close_issue.sh <issue_number>}"
CREDS=$(printf "host=%s\nprotocol=https\n\n" "$HOST" | git credential fill)
USER=$(printf '%s\n' "$CREDS" | sed -n 's/^username=//p')
PASS=$(printf '%s\n' "$CREDS" | sed -n 's/^password=//p')
AUTH=(-u "$USER:$PASS")
PAYLOAD='{"state": "closed"}'
curl -sSL -X PATCH \
-u "$USER:$PASS" \
-H "Content-Type: application/json" \
-d '{"state": "closed"}' \
"$API/repos/$ORG/$REPO/issues/$ISSUE_NUM"
curl -sSL -X PATCH "${AUTH[@]}" -H "Content-Type: application/json" -d "$PAYLOAD" "$API/repos/$ORG/$REPO/issues/$ISSUE_NUM"
echo ""
echo "#$ISSUE_NUM closed"
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
HOST="gitea.dadeschools.net"
API="https://$HOST/api/v1"
ORG="Contractor"
REPO="Timesheet"
CREDS=$(printf "host=%s\nprotocol=https\n\n" "$HOST" | git credential fill)
USER=$(printf '%s\n' "$CREDS" | sed -n 's/^username=//p')
PASS=$(printf '%s\n' "$CREDS" | sed -n 's/^password=//p')
AUTH=(-u "$USER:$PASS")
PAYLOAD='{"title": "feat: Support PTO, Sick, Holiday, and Unpaid days", "body": "Closes #6", "head": "feat/6-absence-categories", "base": "main"}'
curl -sSL -X POST "${AUTH[@]}" -H "Content-Type: application/json" -d "$PAYLOAD" "$API/repos/$ORG/$REPO/pulls"
Executable
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Claim or release a Gitea issue by toggling the `status:in-progress` label, so
# parallel agents/LLMs don't pick up the same issue.
#
# Usage:
# ./mark_issue.sh <issue_number> # claim (adds status:in-progress)
# ./mark_issue.sh <issue_number> start # claim
# ./mark_issue.sh <issue_number> done # release (removes the label)
#
# Auth: macOS keychain via `git credential fill` (same as the other scripts).
set -euo pipefail
HOST="gitea.dadeschools.net"
API="https://$HOST/api/v1"
ORG="Contractor"
REPO="Timesheet"
LABEL="status:in-progress"
NUM="${1:?usage: mark_issue.sh <issue_number> [start|done]}"
ACTION="${2:-start}"
CREDS=$(printf "host=%s\nprotocol=https\n\n" "$HOST" | git credential fill)
USER=$(printf '%s\n' "$CREDS" | sed -n 's/^username=//p')
PASS=$(printf '%s\n' "$CREDS" | sed -n 's/^password=//p')
AUTH=(-u "$USER:$PASS")
# Resolve the label name -> id (Gitea's issue label endpoints take ids).
LID=$(curl -sSL "${AUTH[@]}" "$API/repos/$ORG/$REPO/labels?limit=100" \
| python3 -c "import sys,json;print(next((l['id'] for l in json.load(sys.stdin) if l['name']=='$LABEL'),''))")
if [ -z "$LID" ]; then
echo "Label '$LABEL' not found in $ORG/$REPO -- run manage_labels.py first." >&2
exit 1
fi
case "$ACTION" in
start)
curl -sSL -X POST "${AUTH[@]}" -H "Content-Type: application/json" \
-d "{\"labels\":[$LID]}" "$API/repos/$ORG/$REPO/issues/$NUM/labels" >/dev/null
echo "#$NUM claimed -> $LABEL"
;;
done)
curl -sSL -X DELETE "${AUTH[@]}" \
"$API/repos/$ORG/$REPO/issues/$NUM/labels/$LID" >/dev/null
echo "#$NUM released -> $LABEL removed"
;;
*)
echo "Unknown action '$ACTION' (expected: start | done)" >&2
exit 1
;;
esac