From c5d18b05f3c6238af63539d2240c3bbe79f6a6bb Mon Sep 17 00:00:00 2001 From: Prox Date: Wed, 4 Mar 2026 00:26:20 +0200 Subject: [PATCH] feat: add Gitea Actions CI workflows for dry-run, reconcile, and release --- .gitea/workflows/dry-run.yml | 62 ++++++++++++++++++++++++++++++++ .gitea/workflows/reconcile.yml | 64 ++++++++++++++++++++++++++++++++++ .gitea/workflows/release.yml | 29 +++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 .gitea/workflows/dry-run.yml create mode 100644 .gitea/workflows/reconcile.yml create mode 100644 .gitea/workflows/release.yml diff --git a/.gitea/workflows/dry-run.yml b/.gitea/workflows/dry-run.yml new file mode 100644 index 0000000..596aba9 --- /dev/null +++ b/.gitea/workflows/dry-run.yml @@ -0,0 +1,62 @@ +name: Dry Run + +on: + pull_request: + paths: + - 'netbird.json' + +jobs: + dry-run: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run dry-run reconcile + id: plan + run: | + RESPONSE=$(curl -sf \ + -X POST \ + -H "Authorization: Bearer ${{ secrets.RECONCILER_TOKEN }}" \ + -H "Content-Type: application/json" \ + -d @netbird.json \ + "${{ secrets.RECONCILER_URL }}/reconcile?dry_run=true") + echo "response<> "$GITHUB_OUTPUT" + echo "$RESPONSE" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + - name: Format plan as markdown + id: format + run: | + cat <<'SCRIPT' > format.py + import json, sys + data = json.loads(sys.stdin.read()) + ops = data.get("operations", []) + summary = data.get("summary", {}) + lines = ["## NetBird Reconciliation Plan\n"] + if not ops: + lines.append("No changes detected.\n") + else: + lines.append("| Operation | Name |") + lines.append("|-----------|------|") + for op in ops: + lines.append(f"| `{op['type']}` | {op['name']} |") + lines.append("") + s = summary + lines.append(f"**Summary:** {s.get('created',0)} create, {s.get('updated',0)} update, {s.get('deleted',0)} delete") + print("\n".join(lines)) + SCRIPT + COMMENT=$(echo '${{ steps.plan.outputs.response }}' | python3 format.py) + echo "comment<> "$GITHUB_OUTPUT" + echo "$COMMENT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + - name: Post PR comment + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + curl -sf \ + -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{\"body\": $(echo '${{ steps.format.outputs.comment }}' | jq -Rs .)}" \ + "${{ secrets.GITEA_URL }}/api/v1/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" diff --git a/.gitea/workflows/reconcile.yml b/.gitea/workflows/reconcile.yml new file mode 100644 index 0000000..d05529c --- /dev/null +++ b/.gitea/workflows/reconcile.yml @@ -0,0 +1,64 @@ +name: Reconcile + +on: + push: + branches: + - main + paths: + - 'netbird.json' + +jobs: + reconcile: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Sync events + run: | + curl -sf \ + -X POST \ + -H "Authorization: Bearer ${{ secrets.RECONCILER_TOKEN }}" \ + "${{ secrets.RECONCILER_URL }}/sync-events" + + - name: Pull latest (poller may have committed) + run: git pull --rebase + + - name: Apply reconcile + id: reconcile + run: | + RESPONSE=$(curl -sf \ + -X POST \ + -H "Authorization: Bearer ${{ secrets.RECONCILER_TOKEN }}" \ + -H "Content-Type: application/json" \ + -d @netbird.json \ + "${{ secrets.RECONCILER_URL }}/reconcile") + echo "response<> "$GITHUB_OUTPUT" + echo "$RESPONSE" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + STATUS=$(echo "$RESPONSE" | jq -r '.status') + if [ "$STATUS" = "error" ]; then + echo "Reconcile failed" + echo "$RESPONSE" | jq . + exit 1 + fi + + - name: Encrypt and upload setup keys + if: success() + run: | + KEYS=$(echo '${{ steps.reconcile.outputs.response }}' | jq -r '.created_keys // empty') + if [ -n "$KEYS" ] && [ "$KEYS" != "{}" ] && [ "$KEYS" != "null" ]; then + echo "$KEYS" | age -r "${{ secrets.AGE_PUBLIC_KEY }}" -o setup-keys.age + echo "Setup keys encrypted to setup-keys.age" + else + echo "No new keys created" + exit 0 + fi + + - name: Upload artifact + if: success() + uses: actions/upload-artifact@v4 + with: + name: setup-keys + path: setup-keys.age + if-no-files-found: ignore diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..dd99bcc --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,29 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + build: + runs-on: ubuntu-latest + container: + image: denoland/deno:debian + steps: + - uses: actions/checkout@v4 + + - name: Compile + run: deno compile --allow-net --allow-read --allow-write --allow-env --output reconciler src/main.ts + + - name: Build Docker image + run: | + docker build -t ${{ secrets.GITEA_URL }}/blastpilot/netbird-reconciler:${{ github.ref_name }} . + docker tag ${{ secrets.GITEA_URL }}/blastpilot/netbird-reconciler:${{ github.ref_name }} \ + ${{ secrets.GITEA_URL }}/blastpilot/netbird-reconciler:latest + + - name: Push Docker image + run: | + echo "${{ secrets.PACKAGE_TOKEN }}" | docker login ${{ secrets.GITEA_URL }} -u achilles-ci-bot --password-stdin + docker push ${{ secrets.GITEA_URL }}/blastpilot/netbird-reconciler:${{ github.ref_name }} + docker push ${{ secrets.GITEA_URL }}/blastpilot/netbird-reconciler:latest