|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Smoke test: run all read-only bl commands against a real Backlog space. |
| 3 | +# Usage: ./smoke-test.sh [SPACE_KEY [PROJECT_KEY]] |
| 4 | +set -euo pipefail |
| 5 | + |
| 6 | +SPACE_KEY="${1:-sattg}" |
| 7 | +PROJECT_KEY="${2:-DOTS_TEST}" |
| 8 | +BL="${BL:-$(command -v bl 2>/dev/null || echo "./target/debug/bl")}" |
| 9 | +PASS=0 |
| 10 | +FAIL=0 |
| 11 | +BL_OUT=$(mktemp) |
| 12 | +trap 'rm -f "$BL_OUT"' EXIT |
| 13 | + |
| 14 | +# ── helpers ──────────────────────────────────────────────────────────────────── |
| 15 | + |
| 16 | +run() { |
| 17 | + local label="$1"; shift |
| 18 | + if "$BL" --space "$SPACE_KEY" "$@" > "$BL_OUT" 2>&1; then |
| 19 | + echo " PASS $label" |
| 20 | + PASS=$((PASS + 1)) |
| 21 | + else |
| 22 | + echo " FAIL $label" |
| 23 | + sed 's/^/ /' "$BL_OUT" |
| 24 | + FAIL=$((FAIL + 1)) |
| 25 | + fi |
| 26 | +} |
| 27 | + |
| 28 | +# Run command and capture stdout for later use; still reports PASS/FAIL. |
| 29 | +run_capture() { |
| 30 | + local label="$1"; local varname="$2"; shift 2 |
| 31 | + local output |
| 32 | + if "$BL" --space "$SPACE_KEY" "$@" > "$BL_OUT" 2>&1; then |
| 33 | + echo " PASS $label" |
| 34 | + PASS=$((PASS + 1)) |
| 35 | + output="$(cat "$BL_OUT")" |
| 36 | + printf -v "$varname" '%s' "$output" |
| 37 | + else |
| 38 | + echo " FAIL $label" |
| 39 | + sed 's/^/ /' "$BL_OUT" |
| 40 | + FAIL=$((FAIL + 1)) |
| 41 | + printf -v "$varname" '' |
| 42 | + fi |
| 43 | +} |
| 44 | + |
| 45 | +section() { echo; echo "── $* ──────────────────────────────────────────"; } |
| 46 | + |
| 47 | +jq_or_empty() { |
| 48 | + # Extract a value with jq; return empty string on error. |
| 49 | + local input="$1"; local query="$2" |
| 50 | + echo "$input" | jq -r "$query" 2>/dev/null || true |
| 51 | +} |
| 52 | + |
| 53 | +# ── Phase 1: space (read-only) ───────────────────────────────────────────────── |
| 54 | + |
| 55 | +section "auth" |
| 56 | +run "auth status" auth status |
| 57 | + |
| 58 | +section "space" |
| 59 | +run "space show" space --json |
| 60 | +run "space activities" space activities --json |
| 61 | +run "space disk-usage" space disk-usage --json |
| 62 | +run "space notification" space notification --json |
| 63 | +run "space licence" space licence --json |
| 64 | + |
| 65 | +section "master data" |
| 66 | +run "priority list" priority list --json |
| 67 | +run "resolution list" resolution list --json |
| 68 | +run "rate-limit" rate-limit --json |
| 69 | + |
| 70 | +# ── Phase 2: project ────────────────────────────────────────────────────────── |
| 71 | + |
| 72 | +section "project" |
| 73 | +run "project list" project list --json |
| 74 | +run_capture "project show" PROJ_JSON project show "$PROJECT_KEY" --json |
| 75 | +run "project activities" project activities "$PROJECT_KEY" --json |
| 76 | +run "project disk-usage" project disk-usage "$PROJECT_KEY" --json |
| 77 | +run "project user list" project user list "$PROJECT_KEY" --json |
| 78 | +run "project admin list" project admin list "$PROJECT_KEY" --json |
| 79 | +run "project status list" project status list "$PROJECT_KEY" --json |
| 80 | +run "project issue-type list" project issue-type list "$PROJECT_KEY" --json |
| 81 | +run "project category list" project category list "$PROJECT_KEY" --json |
| 82 | +run "project version list" project version list "$PROJECT_KEY" --json |
| 83 | +run "project team list" project team list "$PROJECT_KEY" --json |
| 84 | +run "project webhook list" project webhook list "$PROJECT_KEY" --json |
| 85 | +run "project custom-field list" project custom-field list "$PROJECT_KEY" --json |
| 86 | + |
| 87 | +PROJECT_ID=$(jq_or_empty "$PROJ_JSON" '.id') |
| 88 | + |
| 89 | +# ── Phase 3: issues ─────────────────────────────────────────────────────────── |
| 90 | + |
| 91 | +section "issue" |
| 92 | +if [[ -n "$PROJECT_ID" ]]; then |
| 93 | + run "issue list" issue list --project-id "$PROJECT_ID" --json |
| 94 | + run "issue count" issue count --project-id "$PROJECT_ID" --json |
| 95 | + run_capture "issue show (first)" ISSUE_JSON issue list --project-id "$PROJECT_ID" --count 1 --json |
| 96 | + ISSUE_KEY=$(jq_or_empty "$ISSUE_JSON" '.[0].issueKey // empty') |
| 97 | +else |
| 98 | + echo " SKIP issue list/count (project ID unavailable)" |
| 99 | + ISSUE_KEY="" |
| 100 | +fi |
| 101 | + |
| 102 | +if [[ -n "$ISSUE_KEY" ]]; then |
| 103 | + run "issue show $ISSUE_KEY" issue show "$ISSUE_KEY" --json |
| 104 | + run "issue comment list" issue comment list "$ISSUE_KEY" --json |
| 105 | + run "issue comment count" issue comment count "$ISSUE_KEY" --json |
| 106 | + run "issue attachment list" issue attachment list "$ISSUE_KEY" --json |
| 107 | + run "issue participant list" issue participant list "$ISSUE_KEY" --json |
| 108 | + run "issue shared-file list" issue shared-file list "$ISSUE_KEY" --json |
| 109 | + |
| 110 | + # comment show (first comment if any) |
| 111 | + run_capture "issue comment list (for id)" CMTS_JSON issue comment list "$ISSUE_KEY" --json |
| 112 | + COMMENT_ID=$(jq_or_empty "$CMTS_JSON" '.[0].id // empty') |
| 113 | + if [[ -n "$COMMENT_ID" ]]; then |
| 114 | + run "issue comment show $COMMENT_ID" issue comment show "$ISSUE_KEY" "$COMMENT_ID" --json |
| 115 | + run "issue comment notification list" issue comment notification list "$ISSUE_KEY" "$COMMENT_ID" --json |
| 116 | + else |
| 117 | + echo " SKIP issue comment show/notification (no comments)" |
| 118 | + fi |
| 119 | +else |
| 120 | + echo " SKIP issue subcommands (no issues found)" |
| 121 | +fi |
| 122 | + |
| 123 | +# ── Phase 4: wiki ───────────────────────────────────────────────────────────── |
| 124 | + |
| 125 | +section "wiki" |
| 126 | +run "wiki list" wiki list "$PROJECT_KEY" --json |
| 127 | +run "wiki count" wiki count "$PROJECT_KEY" --json |
| 128 | +run "wiki tag list" wiki tag list "$PROJECT_KEY" --json |
| 129 | + |
| 130 | +run_capture "wiki list (for id)" WIKIS_JSON wiki list "$PROJECT_KEY" --json |
| 131 | +WIKI_ID=$(jq_or_empty "$WIKIS_JSON" '.[0].id // empty') |
| 132 | + |
| 133 | +if [[ -n "$WIKI_ID" ]]; then |
| 134 | + run "wiki show $WIKI_ID" wiki show "$WIKI_ID" --json |
| 135 | + run "wiki history" wiki history "$WIKI_ID" --json |
| 136 | + run "wiki attachment list" wiki attachment list "$WIKI_ID" --json |
| 137 | + run "wiki shared-file list" wiki shared-file list "$WIKI_ID" --json |
| 138 | + run "wiki star list" wiki star list "$WIKI_ID" --json |
| 139 | +else |
| 140 | + echo " SKIP wiki show/history/attachment/shared-file/star (no wiki pages)" |
| 141 | +fi |
| 142 | + |
| 143 | +# ── Phase 5: documents ──────────────────────────────────────────────────────── |
| 144 | + |
| 145 | +section "document" |
| 146 | +if [[ -n "$PROJECT_ID" ]]; then |
| 147 | + run "document list" document list --project-id "$PROJECT_ID" --json |
| 148 | + run "document tree" document tree "$PROJECT_KEY" --json |
| 149 | + |
| 150 | + run_capture "document list (for id)" DOCS_JSON document list --project-id "$PROJECT_ID" --json |
| 151 | + DOC_ID=$(jq_or_empty "$DOCS_JSON" '.list[0].id // .[0].id // empty') |
| 152 | + if [[ -n "$DOC_ID" ]]; then |
| 153 | + run "document show $DOC_ID" document show "$DOC_ID" --json |
| 154 | + else |
| 155 | + echo " SKIP document show (no documents)" |
| 156 | + fi |
| 157 | +else |
| 158 | + echo " SKIP document (project ID unavailable)" |
| 159 | +fi |
| 160 | + |
| 161 | +# ── Phase 6: shared files ───────────────────────────────────────────────────── |
| 162 | + |
| 163 | +section "shared-file" |
| 164 | +run "shared-file list" shared-file list "$PROJECT_KEY" --json |
| 165 | + |
| 166 | +# ── Phase 7: git / PR ───────────────────────────────────────────────────────── |
| 167 | + |
| 168 | +section "git / pr" |
| 169 | +run_capture "git repo list" REPOS_JSON git repo list "$PROJECT_KEY" --json |
| 170 | +REPO_NAME=$(jq_or_empty "$REPOS_JSON" '.[0].name // empty') |
| 171 | + |
| 172 | +if [[ -n "$REPO_NAME" ]]; then |
| 173 | + run "git repo show" git repo show "$PROJECT_KEY" "$REPO_NAME" --json |
| 174 | + run "pr list" pr list "$PROJECT_KEY" "$REPO_NAME" --json |
| 175 | + run "pr count" pr count "$PROJECT_KEY" "$REPO_NAME" --json |
| 176 | + |
| 177 | + run_capture "pr list (for number)" PRS_JSON pr list "$PROJECT_KEY" "$REPO_NAME" --json |
| 178 | + PR_NUM=$(jq_or_empty "$PRS_JSON" '.[0].number // empty') |
| 179 | + if [[ -n "$PR_NUM" ]]; then |
| 180 | + run "pr show $PR_NUM" pr show "$PROJECT_KEY" "$REPO_NAME" "$PR_NUM" --json |
| 181 | + run "pr comment list" pr comment list "$PROJECT_KEY" "$REPO_NAME" "$PR_NUM" --json |
| 182 | + run "pr comment count" pr comment count "$PROJECT_KEY" "$REPO_NAME" "$PR_NUM" --json |
| 183 | + run "pr attachment list" pr attachment list "$PROJECT_KEY" "$REPO_NAME" "$PR_NUM" --json |
| 184 | + else |
| 185 | + echo " SKIP pr show/comment/attachment (no pull requests)" |
| 186 | + fi |
| 187 | +else |
| 188 | + echo " SKIP git repo show / pr (no git repositories)" |
| 189 | +fi |
| 190 | + |
| 191 | +# ── Phase 8: user ───────────────────────────────────────────────────────────── |
| 192 | + |
| 193 | +section "user" |
| 194 | +run "user list" user list --json |
| 195 | +run "user recently-viewed" user recently-viewed --json |
| 196 | +run "user recently-viewed-projects" user recently-viewed-projects --json |
| 197 | +run "user recently-viewed-wikis" user recently-viewed-wikis --json |
| 198 | + |
| 199 | +run_capture "user list (for id)" USERS_JSON user list --json |
| 200 | +USER_ID=$(jq_or_empty "$USERS_JSON" '.[] | select(.userId != null) | .id' | head -1) |
| 201 | + |
| 202 | +if [[ -n "$USER_ID" ]]; then |
| 203 | + run "user show $USER_ID" user show "$USER_ID" --json |
| 204 | + run "user activities" user activities "$USER_ID" --json |
| 205 | + run "user star list" user star list "$USER_ID" --json |
| 206 | + run "user star count" user star count "$USER_ID" --json |
| 207 | + run "watch list" watch list "$USER_ID" --json |
| 208 | + run "watch count" watch count "$USER_ID" --json |
| 209 | +else |
| 210 | + echo " SKIP user show/activities/star/watch (no users with userId)" |
| 211 | +fi |
| 212 | + |
| 213 | +# ── Phase 9: team (space scope, read-only) ──────────────────────────────────── |
| 214 | + |
| 215 | +section "team" |
| 216 | +run_capture "team list" TEAMS_JSON team list --json |
| 217 | +TEAM_ID=$(jq_or_empty "$TEAMS_JSON" '.[0].id // empty') |
| 218 | +if [[ -n "$TEAM_ID" ]]; then |
| 219 | + run "team show $TEAM_ID" team show "$TEAM_ID" --json |
| 220 | +else |
| 221 | + echo " SKIP team show (no teams)" |
| 222 | +fi |
| 223 | + |
| 224 | +# ── Phase 10: notification (space scope, read-only) ─────────────────────────── |
| 225 | + |
| 226 | +section "notification" |
| 227 | +run "notification list" notification list --json |
| 228 | +run "notification count" notification count --json |
| 229 | + |
| 230 | +# ── summary ─────────────────────────────────────────────────────────────────── |
| 231 | + |
| 232 | +echo |
| 233 | +echo "════════════════════════════════════════" |
| 234 | +echo " PASS: $PASS FAIL: $FAIL" |
| 235 | +echo "════════════════════════════════════════" |
| 236 | +[[ "$FAIL" -eq 0 ]] |
0 commit comments