#!/usr/bin/env bash # gl — GitLab API helper for lean-ctx (Project ID 5) # Works around Traefik's %2F rejection by using numeric project ID. # # Usage: # gl issues # list open issues # gl issue 290 # show issue #290 # gl close 290 # close issue #290 # gl comment 290 "Done" # add note to issue #290 # gl create "Title" "Desc" "label1,label2" # create issue # gl epics # list open epics (label type::epic) # gl api # raw API call (project-scoped) set -euo pipefail # Auth comes from the environment or glab's keyring (`glab auth login`). # NEVER hardcode a token here: this file is tracked in git, including the # public GitHub mirror. If GITLAB_TOKEN is unset, glab uses its keyring. export GITLAB_HOST="${GITLAB_HOST:-gitlab.pounce.ch}" PROJECT_ID=5 BASE="projects/${PROJECT_ID}" cmd="${1:-help}" shift || true case "$cmd" in issues|list) state="${1:-opened}" glab api "${BASE}/issues?state=${state}&per_page=50&order_by=updated_at" | \ python3 -c " import sys, json issues = json.loads(sys.stdin.read()) for i in issues: labels = ', '.join(i.get('labels', [])) print(f'#{i[\"iid\"]:>4} {i[\"state\"]:8} {i[\"title\"][:72]} [{labels}]') " ;; issue|show) iid="${1:?Usage: gl issue }" glab api "${BASE}/issues/${iid}" | python3 -c " import sys, json i = json.loads(sys.stdin.read()) print(f'#{i[\"iid\"]} [{i[\"state\"]}] {i[\"title\"]}') print(f'Labels: {\", \".join(i.get(\"labels\", []))}') print(f'Created: {i[\"created_at\"][:10]} Updated: {i[\"updated_at\"][:10]}') if i.get('description'): print(f'\\n{i[\"description\"][:500]}') " ;; close) iid="${1:?Usage: gl close }" glab api --method PUT "${BASE}/issues/${iid}" -f state_event=close >/dev/null echo "Closed #${iid}" ;; reopen) iid="${1:?Usage: gl reopen }" glab api --method PUT "${BASE}/issues/${iid}" -f state_event=reopen >/dev/null echo "Reopened #${iid}" ;; comment|note) iid="${1:?Usage: gl comment }" body="${2:?Usage: gl comment }" glab api --method POST "${BASE}/issues/${iid}/notes" -f body="${body}" >/dev/null echo "Comment added to #${iid}" ;; create) title="${1:?Usage: gl create [description] [labels]}" desc="${2:-}" labels="${3:-}" args=(-f "title=${title}") [[ -n "$desc" ]] && args+=(-f "description=${desc}") [[ -n "$labels" ]] && args+=(-f "labels=${labels}") result=$(glab api --method POST "${BASE}/issues" "${args[@]}") iid=$(echo "$result" | python3 -c "import sys,json; print(json.loads(sys.stdin.read())['iid'])") echo "Created #${iid}: ${title}" ;; epics) glab api "${BASE}/issues?state=opened&labels=type::epic&per_page=50" | \ python3 -c " import sys, json for i in json.loads(sys.stdin.read()): print(f'#{i[\"iid\"]:>4} {i[\"title\"][:80]}') " ;; api) glab api "${BASE}/${1}" "${@:2}" ;; help|--help|-h) echo "gl — GitLab API helper (lean-ctx, project #5)" echo "" echo "Commands:" echo " issues [state] List issues (default: opened)" echo " issue <iid> Show issue details" echo " close <iid> Close an issue" echo " reopen <iid> Reopen an issue" echo " comment <iid> <body> Add a note" echo " create <title> [desc] [labels] Create issue" echo " epics List open epics" echo " api <path> [args...] Raw project-scoped API call" ;; *) echo "Unknown command: $cmd (try: gl help)" >&2 exit 1 ;; esac