Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

95 lines · 4.8 KBRaw History
1name: Move to Diffinery
2
3# Copies this repository to diffinery.com/codician-team/diffinery: every branch
4# and tag, plus the Actions secrets and variables our workflows use. Safe to
5# re-run; each run brings Diffinery up to date.
6#
7# Secrets go straight from GitHub's secret store to Diffinery's over HTTPS and are
8# never printed. Needs DIFFINERY_LIVE_TOKEN (an admin token on diffinery.com).
9on:
10 workflow_dispatch:
11
12permissions:
13 contents: read
14
15concurrency:
16 group: move-to-diffinery
17 cancel-in-progress: false
18
19jobs:
20 move:
21 name: Copy code, secrets and variables
22 runs-on: ubuntu-latest
23 timeout-minutes: 20
24 environment: production
25 env:
26 DIFFINERY: https://diffinery.com
27 TOKEN: ${{ secrets.DIFFINERY_LIVE_TOKEN }}
28 ORG: codician-team
29 NAME: diffinery
30 steps:
31 - name: Check the token
32 run: |
33 [ -n "$TOKEN" ] || { echo "::error::Add DIFFINERY_LIVE_TOKEN (an admin token from $DIFFINERY/settings/tokens) as a repository secret first."; exit 1; }
34 curl -fsS "$DIFFINERY/api/v3/user" -H "Authorization: Bearer $TOKEN" | jq '{login, site_admin}'
35
36 - name: Create the organization and repository
37 env:
38 DESC: ${{ github.event.repository.description }}
39 run: |
40 set -euo pipefail
41 api() { curl -sS -o /tmp/out -w '%{http_code}' -X "$1" "$DIFFINERY/api/v3$2" -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" ${3:+--data "$3"}; }
42 if [ "$(api GET "/users/$ORG")" = 404 ]; then
43 code=$(api POST /user/orgs "{\"login\":\"$ORG\",\"name\":\"Codician\"}"); cat /tmp/out; echo
44 [ "$code" = 201 ] || { echo "::error::could not create the $ORG organization ($code)"; exit 1; }
45 fi
46 if [ "$(api GET "/repos/$ORG/$NAME")" = 404 ]; then
47 desc=$(jq -n --arg d "$DESC" '$d')
48 code=$(api POST "/orgs/$ORG/repos" "{\"name\":\"$NAME\",\"private\":true,\"default_branch\":\"main\",\"description\":$desc}"); cat /tmp/out; echo
49 [ "$code" = 201 ] || { echo "::error::could not create $ORG/$NAME ($code)"; exit 1; }
50 fi
51 echo "$DIFFINERY/$ORG/$NAME is ready"
52
53 - name: Copy Actions secrets and variables
54 env:
55 S_CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
56 S_CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
57 S_DIFFINERY_LIVE_TOKEN: ${{ secrets.DIFFINERY_LIVE_TOKEN }}
58 V_ACCESS_TEAM_DOMAIN: ${{ vars.ACCESS_TEAM_DOMAIN }}
59 run: |
60 set -euo pipefail
61 put() { curl -fsS -o /dev/null -X PUT "$DIFFINERY/api/v3/repos/$ORG/$NAME/actions/$1/$2" -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" --data-binary @-; }
62 for name in CLOUDFLARE_API_TOKEN CLOUDFLARE_ACCOUNT_ID DIFFINERY_LIVE_TOKEN; do
63 v="S_$name"
64 if [ -n "${!v}" ]; then jq -n --arg v "${!v}" '{value: $v}' | put secrets "$name"; echo "secret $name copied"; else echo "::warning::secret $name is empty here, so it was not copied"; fi
65 done
66 for name in ACCESS_TEAM_DOMAIN; do
67 v="V_$name"
68 if [ -n "${!v}" ]; then jq -n --arg v "${!v}" '{value: $v}' | put variables "$name"; echo "variable $name = ${!v}"; fi
69 done
70
71 - uses: actions/checkout@v4
72 with:
73 fetch-depth: 0
74 lfs: true
75
76 - name: Push every branch and tag
77 run: |
78 set -euo pipefail
79 git fetch -q --tags origin '+refs/heads/*:refs/remotes/origin/*'
80 remote="https://x-token:${TOKEN}@${DIFFINERY#https://}/$ORG/$NAME.git"
81 refs=$(git for-each-ref --format='+%(refname):refs/heads/%(refname:lstrip=3)' refs/remotes/origin | grep -v ':refs/heads/HEAD$')
82 git push -q "$remote" $refs '+refs/tags/*:refs/tags/*'
83 if git lfs ls-files | grep -q .; then git lfs push --all "$remote"; fi
84 echo "branches on Diffinery:"
85 curl -fsS "$DIFFINERY/api/v3/repos/$ORG/$NAME/branches" -H "Authorization: Bearer $TOKEN" | jq -r '.[] | " \(.name) \(.commit.sha)"'
86 want=$(git rev-parse refs/remotes/origin/main)
87 got=$(curl -fsS "$DIFFINERY/api/v3/repos/$ORG/$NAME/branches" -H "Authorization: Bearer $TOKEN" | jq -r '.[] | select(.name=="main") | .commit.sha')
88 [ "$want" = "$got" ] || { echo "::error::main on Diffinery is $got, expected $want"; exit 1; }
89 echo "main matches GitHub at $want"
90
91 - name: Check Actions on Diffinery
92 run: |
93 set -euo pipefail
94 curl -fsS "$DIFFINERY/api/v3/repos/$ORG/$NAME/actions/workflows" -H "Authorization: Bearer $TOKEN" | jq -r '.workflows[] | "\(.path): \(.state) \(.errors | join("; "))"'
95 curl -fsS "$DIFFINERY/api/v3/repos/$ORG/$NAME/actions/secrets" -H "Authorization: Bearer $TOKEN" | jq -r '.secrets[] | "secret \(.name)"'