create_github_repo.sh 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #!/usr/bin/env bash
  2. # =============================================================================
  3. # create_github_repo.sh
  4. # One-shot script to:
  5. # 1) Create the GitHub repository conexocasa/solar-of-things-ha (if missing)
  6. # 2) Push main branch + all tags (v2.1.0, v2.1.1)
  7. # 3) Create a DRAFT GitHub Release for v2.1.1 and upload solar-of-things-ha.zip
  8. #
  9. # Usage:
  10. # export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
  11. # bash create_github_repo.sh
  12. #
  13. # Requirements: git, curl, jq (installed by script if missing)
  14. # =============================================================================
  15. set -euo pipefail
  16. # ── Config ────────────────────────────────────────────────────────────────────
  17. GITHUB_USERNAME="conexocasa"
  18. GITHUB_EMAIL="bob@conexo.casa"
  19. REPO_NAME="solar-of-things-ha"
  20. REPO_DESC="Home Assistant custom integration for Solar of Things (Siseli) solar inverters — monitoring + control"
  21. RELEASE_TAG="v2.1.1"
  22. RELEASE_TITLE="v2.1.1 — HACS metadata, GitHub Actions, issue templates"
  23. ZIP_ASSET="solar-of-things-ha.zip"
  24. # ─────────────────────────────────────────────────────────────────────────────
  25. RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
  26. ok() { echo -e "${GREEN}✓${NC} $*"; }
  27. warn() { echo -e "${YELLOW}⚠${NC} $*"; }
  28. err() { echo -e "${RED}✗${NC} $*"; exit 1; }
  29. # ── Token ─────────────────────────────────────────────────────────────────────
  30. if [ -z "${GITHUB_TOKEN:-}" ]; then
  31. echo -n "GitHub Personal Access Token (repo scope): "
  32. read -s GITHUB_TOKEN
  33. echo
  34. fi
  35. [ -z "$GITHUB_TOKEN" ] && err "GITHUB_TOKEN is required."
  36. API="https://api.github.com"
  37. AUTH_HEADER="Authorization: token $GITHUB_TOKEN"
  38. ACCEPT="Accept: application/vnd.github.v3+json"
  39. # ── Dependencies ──────────────────────────────────────────────────────────────
  40. if ! command -v jq &>/dev/null; then
  41. warn "jq not found — installing…"
  42. apt-get install -y -q jq 2>/dev/null || brew install jq 2>/dev/null || err "Install jq manually."
  43. fi
  44. # ── Git identity ──────────────────────────────────────────────────────────────
  45. git config --global user.email "$GITHUB_EMAIL"
  46. git config --global user.name "$GITHUB_USERNAME"
  47. ok "Git identity set ($GITHUB_EMAIL)"
  48. # ── Step 1: Create repository (idempotent) ────────────────────────────────────
  49. echo ""
  50. echo "══════════════════════════════════════════════"
  51. echo " STEP 1 · Create GitHub repository"
  52. echo "══════════════════════════════════════════════"
  53. RESP=$(curl -s -o /tmp/gh_create.json -w "%{http_code}" \
  54. -X POST "$API/user/repos" \
  55. -H "$AUTH_HEADER" -H "$ACCEPT" \
  56. -d "{
  57. \"name\":\"$REPO_NAME\",
  58. \"description\":\"$REPO_DESC\",
  59. \"private\":false,
  60. \"has_issues\":true,
  61. \"has_projects\":false,
  62. \"has_wiki\":false,
  63. \"default_branch\":\"main\"
  64. }")
  65. if [ "$RESP" = "201" ]; then
  66. ok "Repository created: https://github.com/$GITHUB_USERNAME/$REPO_NAME"
  67. elif [ "$RESP" = "422" ]; then
  68. warn "Repository already exists — continuing."
  69. else
  70. cat /tmp/gh_create.json
  71. err "Unexpected HTTP $RESP from repo creation."
  72. fi
  73. # ── Step 2: Push main + all tags ──────────────────────────────────────────────
  74. echo ""
  75. echo "══════════════════════════════════════════════"
  76. echo " STEP 2 · Push main branch + tags"
  77. echo "══════════════════════════════════════════════"
  78. REMOTE_URL="https://${GITHUB_TOKEN}@github.com/${GITHUB_USERNAME}/${REPO_NAME}.git"
  79. git remote remove origin 2>/dev/null || true
  80. git remote add origin "$REMOTE_URL"
  81. git branch -M main
  82. if git push origin main --force; then
  83. ok "Pushed branch main"
  84. else
  85. err "Failed to push main"
  86. fi
  87. if git push origin --tags --force; then
  88. ok "Pushed all tags ($(git tag --list | tr '\n' ' '))"
  89. else
  90. err "Failed to push tags"
  91. fi
  92. # Clean up token from remote URL
  93. git remote set-url origin "https://github.com/${GITHUB_USERNAME}/${REPO_NAME}.git"
  94. # ── Step 3: Create draft GitHub Release for RELEASE_TAG ───────────────────────
  95. echo ""
  96. echo "══════════════════════════════════════════════"
  97. echo " STEP 3 · Create draft release $RELEASE_TAG"
  98. echo "══════════════════════════════════════════════"
  99. # Extract changelog section for RELEASE_TAG
  100. VER="${RELEASE_TAG#v}"
  101. RELEASE_BODY=$(awk "/^## \[$VER\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md || true)
  102. if [ -z "$RELEASE_BODY" ]; then
  103. RELEASE_BODY="See CHANGELOG.md for full details."
  104. fi
  105. RELEASE_BODY_JSON=$(jq -Rs . <<< "$RELEASE_BODY")
  106. # Delete existing draft for same tag if any
  107. EXISTING_ID=$(curl -s -H "$AUTH_HEADER" -H "$ACCEPT" \
  108. "$API/repos/$GITHUB_USERNAME/$REPO_NAME/releases" \
  109. | jq -r ".[] | select(.tag_name==\"$RELEASE_TAG\") | .id" | head -1)
  110. if [ -n "$EXISTING_ID" ]; then
  111. warn "Deleting existing release id=$EXISTING_ID for $RELEASE_TAG"
  112. curl -s -X DELETE "$API/repos/$GITHUB_USERNAME/$REPO_NAME/releases/$EXISTING_ID" \
  113. -H "$AUTH_HEADER" -H "$ACCEPT" > /dev/null
  114. fi
  115. RELEASE_RESP=$(curl -s -X POST \
  116. "$API/repos/$GITHUB_USERNAME/$REPO_NAME/releases" \
  117. -H "$AUTH_HEADER" -H "$ACCEPT" \
  118. -d "{
  119. \"tag_name\":\"$RELEASE_TAG\",
  120. \"target_commitish\":\"main\",
  121. \"name\":\"$RELEASE_TITLE\",
  122. \"body\":$RELEASE_BODY_JSON,
  123. \"draft\":true,
  124. \"prerelease\":false
  125. }")
  126. RELEASE_ID=$(echo "$RELEASE_RESP" | jq -r '.id // empty')
  127. UPLOAD_URL=$(echo "$RELEASE_RESP" | jq -r '.upload_url // empty' | sed 's/{.*}//')
  128. if [ -z "$RELEASE_ID" ]; then
  129. echo "$RELEASE_RESP"
  130. err "Failed to create draft release."
  131. fi
  132. ok "Draft release created (id=$RELEASE_ID)"
  133. # ── Step 4: Upload ZIP asset ──────────────────────────────────────────────────
  134. echo ""
  135. echo "══════════════════════════════════════════════"
  136. echo " STEP 4 · Upload $ZIP_ASSET"
  137. echo "══════════════════════════════════════════════"
  138. # Locate the zip file (same dir as script, or outputs dir)
  139. SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
  140. ZIP_PATH=""
  141. for candidate in \
  142. "$SCRIPT_DIR/$ZIP_ASSET" \
  143. "/mnt/user-data/outputs/$ZIP_ASSET" \
  144. "$(pwd)/$ZIP_ASSET"; do
  145. if [ -f "$candidate" ]; then
  146. ZIP_PATH="$candidate"
  147. break
  148. fi
  149. done
  150. if [ -z "$ZIP_PATH" ]; then
  151. warn "Could not find $ZIP_ASSET — skipping upload."
  152. warn "To upload manually: attach '$ZIP_ASSET' on the draft release page:"
  153. echo " https://github.com/$GITHUB_USERNAME/$REPO_NAME/releases/edit/$RELEASE_ID"
  154. else
  155. UPLOAD_RESP=$(curl -s -X POST \
  156. "${UPLOAD_URL}?name=${ZIP_ASSET}&label=${ZIP_ASSET}" \
  157. -H "$AUTH_HEADER" \
  158. -H "Content-Type: application/zip" \
  159. --data-binary @"$ZIP_PATH")
  160. ASSET_URL=$(echo "$UPLOAD_RESP" | jq -r '.browser_download_url // empty')
  161. if [ -n "$ASSET_URL" ]; then
  162. ok "Asset uploaded: $ASSET_URL"
  163. else
  164. warn "Asset upload may have failed:"
  165. echo "$UPLOAD_RESP" | jq '.' 2>/dev/null || echo "$UPLOAD_RESP"
  166. fi
  167. fi
  168. # ── Done ──────────────────────────────────────────────────────────────────────
  169. echo ""
  170. echo "══════════════════════════════════════════════"
  171. echo " SUCCESS"
  172. echo "══════════════════════════════════════════════"
  173. echo ""
  174. echo " Repository : https://github.com/$GITHUB_USERNAME/$REPO_NAME"
  175. echo " Branch : main"
  176. echo " Tags : $(git tag --list | tr '\n' ' ')"
  177. echo " Draft release page:"
  178. echo " https://github.com/$GITHUB_USERNAME/$REPO_NAME/releases/edit/$RELEASE_ID"
  179. echo ""
  180. echo " Next steps:"
  181. echo " 1. Visit the draft release link above."
  182. echo " 2. Review release notes and attached ZIP."
  183. echo " 3. Click 'Publish release' when ready."
  184. echo " 4. For HACS: Settings → Devices & Services → Add Integration → Solar of Things"
  185. echo ""