|
| 1 | +name: Verify SDK & Publish Release |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + branches: [main] |
| 6 | + tags: ["v*"] |
| 7 | + workflow_dispatch: |
| 8 | + |
| 9 | +permissions: |
| 10 | + contents: write |
| 11 | + |
| 12 | +jobs: |
| 13 | + verify-and-release: |
| 14 | + runs-on: ubuntu-latest |
| 15 | + steps: |
| 16 | + - name: Checkout repository |
| 17 | + uses: actions/checkout@v4 |
| 18 | + |
| 19 | + - name: Verify Python SDK scripts & JSON schemas |
| 20 | + run: | |
| 21 | + python3 -m py_compile examples/*.py |
| 22 | + python3 -c 'import glob, json; [json.load(open(f)) for f in glob.glob("n8n/*.json") + glob.glob("samples/*.json") + glob.glob("notebooks/*.ipynb")]' |
| 23 | +
|
| 24 | + - name: Build starter-kit release bundle (unitbytes-reddit-scraper-api-starter-kit.zip) |
| 25 | + run: | |
| 26 | + zip -r "unitbytes-reddit-scraper-api-starter-kit.zip" README.md requirements.txt LICENSE SECURITY.md examples/ notebooks/ n8n/ samples/ |
| 27 | +
|
| 28 | + - name: Sync clean v1.0.0 & v1.1.0 GitHub Releases |
| 29 | + env: |
| 30 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 31 | + REPO_FULL: ${{ github.repository }} |
| 32 | + TITLE_CLEAN: "🤖 Reddit Scraper API Suite: Subreddits, Search, Posts & Nested Comments (`$1 / 1K`)" |
| 33 | + ZIP_NAME: "unitbytes-reddit-scraper-api-starter-kit.zip" |
| 34 | + run: | |
| 35 | + python3 - << 'PYEOF' |
| 36 | + import json, os, subprocess, urllib.request |
| 37 | +
|
| 38 | + token = os.environ["GH_TOKEN"] |
| 39 | + repo = os.environ["REPO_FULL"] |
| 40 | + title_clean = os.environ["TITLE_CLEAN"] |
| 41 | + zip_name = os.environ["ZIP_NAME"] |
| 42 | + notes_v110 = open(".github/RELEASE_NOTES.md", "r", encoding="utf-8").read() |
| 43 | + notes_v100 = notes_v110.replace("v1.1.0 Release Notes", "v1.0.0 Release Notes", 1) |
| 44 | +
|
| 45 | + def gh_api(method, path, payload=None): |
| 46 | + url = f"https://api.github.com{path}" |
| 47 | + headers = { |
| 48 | + "Accept": "application/vnd.github+json", |
| 49 | + "Authorization": f"Bearer {token}", |
| 50 | + "X-GitHub-Api-Version": "2022-11-28", |
| 51 | + "User-Agent": "unitbytes-release-bot", |
| 52 | + } |
| 53 | + data = None |
| 54 | + if payload is not None: |
| 55 | + data = json.dumps(payload).encode("utf-8") |
| 56 | + headers["Content-Type"] = "application/json" |
| 57 | + req = urllib.request.Request(url, data=data, headers=headers, method=method) |
| 58 | + with urllib.request.urlopen(req, timeout=30) as r: |
| 59 | + b = r.read().decode("utf-8") |
| 60 | + return json.loads(b) if b else {} |
| 61 | +
|
| 62 | + rels = gh_api("GET", f"/repos/{repo}/releases") |
| 63 | + by_tag = {r["tag_name"]: r for r in rels} |
| 64 | +
|
| 65 | + if "v1.0.0" in by_tag: |
| 66 | + r100 = by_tag["v1.0.0"] |
| 67 | + gh_api("PATCH", f"/repos/{repo}/releases/{r100['id']}", { |
| 68 | + "name": f"UnitBytes {title_clean} — v1.0.0 Release", |
| 69 | + "body": notes_v100, |
| 70 | + }) |
| 71 | +
|
| 72 | + rel_name_110 = f"UnitBytes {title_clean} — v1.1.0 (Colab, MCP, RapidAPI/Zyla & 9-Node n8n Suite)" |
| 73 | + if "v1.1.0" in by_tag: |
| 74 | + r110 = by_tag["v1.1.0"] |
| 75 | + gh_api("PATCH", f"/repos/{repo}/releases/{r110['id']}", { |
| 76 | + "name": rel_name_110, |
| 77 | + "body": notes_v110, |
| 78 | + "draft": False, |
| 79 | + "prerelease": False, |
| 80 | + "make_latest": "true", |
| 81 | + }) |
| 82 | + else: |
| 83 | + gh_api("POST", f"/repos/{repo}/releases", { |
| 84 | + "tag_name": "v1.1.0", |
| 85 | + "target_commitish": "main", |
| 86 | + "name": rel_name_110, |
| 87 | + "body": notes_v110, |
| 88 | + "draft": False, |
| 89 | + "prerelease": False, |
| 90 | + "make_latest": "true", |
| 91 | + }) |
| 92 | +
|
| 93 | + subprocess.run(["gh", "release", "upload", "v1.1.0", zip_name, "--clobber", "--repo", repo], check=True) |
| 94 | + PYEOF |
0 commit comments