Skip to content

Commit 8cd10ed

Browse files
ci: auto deploy codex on devnet (#1302)
1 parent 6cf99e2 commit 8cd10ed

File tree

3 files changed

+220
-21
lines changed

3 files changed

+220
-21
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
name: Deploy - Devnet
2+
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
codex_image:
8+
description: codexstorage/nim-codex:latest-dist-tests
9+
required: false
10+
type: string
11+
workflow_call:
12+
inputs:
13+
codex_image:
14+
description: codexstorage/nim-codex:latest-dist-tests
15+
required: true
16+
type: string
17+
18+
env:
19+
CODEX_NAMESPACE: codex
20+
TOOLS_NAMESPACE: common
21+
KUBE_CONFIG: ${{ secrets.DEVNET_KUBE_CONFIG }}
22+
KUBE_VERSION: v1.33.1
23+
CODEX_IMAGE: ${{ inputs.codex_image }}
24+
SSH_HOSTS: ${{ secrets.DEVNET_SSH_HOSTS }}
25+
SSH_PORT: ${{ secrets.DEVNET_SSH_PORT }}
26+
SSH_USERNAME: ${{ secrets.DEVNET_SSH_USERNAME }}
27+
SSH_PRIVATE_KEY: ${{ secrets.DEVNET_SSH_KEY }}
28+
29+
30+
jobs:
31+
deploy-contracts:
32+
name: Deploy contracts
33+
runs-on: ubuntu-latest
34+
steps:
35+
- name: Create access token
36+
uses: actions/create-github-app-token@v2
37+
id: app-token
38+
with:
39+
app-id: ${{ secrets.DEPLOYER_APP_ID }}
40+
private-key: ${{ secrets.DEPLOYER_PRIVATE_KEY }}
41+
repositories: codex-contracts-eth
42+
43+
- name: Checkout sources
44+
uses: actions/checkout@v4
45+
with:
46+
submodules: recursive
47+
48+
- name: Get contracts submodule ref
49+
id: contracts
50+
run: echo "ref=$(git rev-parse HEAD:vendor/codex-contracts-eth)" >> $GITHUB_OUTPUT
51+
52+
- name: Deploy smart contracts
53+
uses: the-actions-org/workflow-dispatch@v4
54+
with:
55+
repo: codex-storage/codex-contracts-eth
56+
workflow: devnet-contracts.yml
57+
token: ${{ steps.app-token.outputs.token }}
58+
wait-for-completion-timeout: 20m
59+
wait-for-completion-interval: 20s
60+
inputs: '{ "network": "codex_devnet", "contracts_ref": "${{ steps.contracts.outputs.ref }}" }'
61+
62+
63+
bootstrap-nodes:
64+
name: Bootstrap nodes
65+
runs-on: ubuntu-latest
66+
needs: deploy-contracts
67+
steps:
68+
- name: Codex Bootstrap - Update
69+
uses: appleboy/ssh-action@v1
70+
with:
71+
host: ${{ secrets.DEVNET_SSH_HOSTS }}
72+
username: ${{ secrets.DEVNET_SSH_USERNAME }}
73+
key: ${{ secrets.DEVNET_SSH_KEY }}
74+
port: ${{ secrets.DEVNET_SSH_PORT }}
75+
script: /opt/codex/remote-deploy.sh ${{ env.CODEX_IMAGE }}
76+
77+
cluster-nodes:
78+
name: Cluster nodes
79+
runs-on: ubuntu-latest
80+
needs: bootstrap-nodes
81+
steps:
82+
- name: Kubectl - Install ${{ env.KUBE_VERSION }}
83+
uses: azure/setup-kubectl@v4
84+
with:
85+
version: ${{ env.KUBE_VERSION }}
86+
87+
- name: Kubectl - Kubeconfig
88+
run: |
89+
mkdir -p "${HOME}"/.kube
90+
echo "${{ env.KUBE_CONFIG }}" | base64 -d > "${HOME}"/.kube/config
91+
92+
- name: Codex Storage - Update
93+
run: |
94+
for node in {1..5}; do
95+
kubectl -n "${{ env.CODEX_NAMESPACE }}" patch statefulset codex-storage-${node} \
96+
--patch '{"spec": {"template": {"spec":{"containers":[{"name": "codex", "image":"${{ env.CODEX_IMAGE }}"}]}}}}'
97+
done
98+
99+
- name: Codex Validators - Update
100+
run: |
101+
for node in {1..1}; do
102+
kubectl -n "${{ env.CODEX_NAMESPACE }}" patch statefulset codex-validator-${node} \
103+
--patch '{"spec": {"template": {"spec":{"containers":[{"name": "codex", "image":"${{ env.CODEX_IMAGE }}"}]}}}}'
104+
done
105+
106+
- name: Codex Storage - Status
107+
run: |
108+
WAIT=300
109+
SECONDS=0
110+
sleep=1
111+
for instance in {1..5}; do
112+
while (( SECONDS < WAIT )); do
113+
pod=codex-storage-${instance}-1
114+
phase=$(kubectl get pod "${pod}" -n "${{ env.CODEX_NAMESPACE }}" -o jsonpath='{.status.phase}')
115+
if [[ "${phase}" == "Running" ]]; then
116+
echo "Pod ${pod} is in the ${phase} state"
117+
break
118+
else
119+
echo "Pod ${pod} is in the ${phase} state - Check in ${sleep} second(s) / $((WAIT - SECONDS))"
120+
fi
121+
sleep "${sleep}"
122+
done
123+
done
124+
125+
- name: Codex Validators - Status
126+
run: |
127+
WAIT=300
128+
SECONDS=0
129+
sleep=1
130+
for instance in {1..1}; do
131+
while (( SECONDS < WAIT )); do
132+
pod=codex-validator-${instance}-1
133+
phase=$(kubectl get pod "${pod}" -n "${{ env.CODEX_NAMESPACE }}" -o jsonpath='{.status.phase}')
134+
if [[ "${phase}" == "Running" ]]; then
135+
echo "Pod ${pod} is in the ${phase} state"
136+
break
137+
else
138+
echo "Pod ${pod} is in the ${phase} state - Check in ${sleep} second(s) / $((WAIT - SECONDS))"
139+
fi
140+
sleep "${sleep}"
141+
done
142+
done
143+
144+
- name: Tools - Update
145+
run: |
146+
crawler_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app.kubernetes.io/name=crawler' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
147+
discordbot_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app=discordbot' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
148+
149+
for pod in "${crawler_pod}" "${discordbot_pod}"; do
150+
if [[ -n "${pod}" ]]; then
151+
kubectl delete pod -n "${{ env.TOOLS_NAMESPACE }}" "${pod}" --grace-period=10
152+
fi
153+
done
154+
155+
- name: Tools - Status
156+
run: |
157+
WAIT=300
158+
SECONDS=0
159+
sleep=1
160+
crawler_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app.kubernetes.io/name=crawler' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
161+
discordbot_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app=discordbot' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
162+
for pod in "${crawler_pod}" "${discordbot_pod}"; do
163+
if [[ -n "${pod}" ]]; then
164+
while (( SECONDS < WAIT )); do
165+
phase=$(kubectl get pod "${pod}" -n "${{ env.TOOLS_NAMESPACE }}" -o jsonpath='{.status.phase}')
166+
if [[ "${phase}" == "Running" ]]; then
167+
echo "Pod ${pod} is in the ${phase} state"
168+
break
169+
else
170+
echo "Pod ${pod} is in the ${phase} state - Check in ${sleep} second(s) / $((WAIT - SECONDS))"
171+
fi
172+
sleep "${sleep}"
173+
done
174+
fi
175+
done

.github/workflows/docker-dist-tests.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ on:
1313
- '.github/**'
1414
- '!.github/workflows/docker-dist-tests.yml'
1515
- '!.github/workflows/docker-reusable.yml'
16+
- '!.github/workflows/deploy-devnet.yml'
1617
- 'docker/**'
1718
- '!docker/codex.Dockerfile'
1819
- '!docker/docker-entrypoint.sh'
@@ -23,6 +24,11 @@ on:
2324
required: false
2425
type: boolean
2526
default: false
27+
deploy_devnet:
28+
description: Deploy Devnet
29+
required: false
30+
type: boolean
31+
default: false
2632

2733

2834
jobs:
@@ -40,6 +46,7 @@ jobs:
4046
run: |
4147
hash=$(git rev-parse --short HEAD:vendor/codex-contracts-eth)
4248
echo "hash=$hash" >> $GITHUB_OUTPUT
49+
4350
build-and-push:
4451
name: Build and Push
4552
uses: ./.github/workflows/docker-reusable.yml
@@ -53,3 +60,12 @@ jobs:
5360
contract_image: "codexstorage/codex-contracts-eth:sha-${{ needs.get-contracts-hash.outputs.hash }}-dist-tests"
5461
run_release_tests: ${{ inputs.run_release_tests }}
5562
secrets: inherit
63+
64+
deploy-devnet:
65+
name: Deploy Devnet
66+
uses: ./.github/workflows/deploy-devnet.yml
67+
needs: build-and-push
68+
if: ${{ inputs.deploy_devnet || github.event_name == 'push' && github.ref_name == github.event.repository.default_branch }}
69+
with:
70+
codex_image: ${{ needs.build-and-push.outputs.codex_image }}
71+
secrets: inherit

.github/workflows/docker-reusable.yml

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ on:
6868
description: Specifies compatible smart contract image
6969
required: false
7070
type: string
71+
outputs:
72+
codex_image:
73+
description: Codex Docker image tag
74+
value: ${{ jobs.publish.outputs.codex_image }}
7175

7276

7377
env:
@@ -91,15 +95,16 @@ env:
9195

9296

9397
jobs:
98+
# Compute variables
9499
compute:
95-
name: Compute build ID
96-
runs-on: ubuntu-latest
97-
outputs:
98-
build_id: ${{ steps.build_id.outputs.build_id }}
99-
steps:
100-
- name: Generate unique build id
101-
id: build_id
102-
run: echo "build_id=$(openssl rand -hex 5)" >> $GITHUB_OUTPUT
100+
name: Compute build ID
101+
runs-on: ubuntu-latest
102+
outputs:
103+
build_id: ${{ steps.build_id.outputs.build_id }}
104+
steps:
105+
- name: Generate unique build id
106+
id: build_id
107+
run: echo "build_id=$(openssl rand -hex 5)" >> $GITHUB_OUTPUT
103108

104109
# Build platform specific image
105110
build:
@@ -134,7 +139,7 @@ jobs:
134139
run: |
135140
# Create contract label for compatible contract image if specified
136141
if [[ -n "${{ env.CONTRACT_IMAGE }}" ]]; then
137-
echo "CONTRACT_LABEL=storage.codex.nim-codex.blockchain-image=${{ env.CONTRACT_IMAGE }}" >>$GITHUB_ENV
142+
echo "CONTRACT_LABEL=storage.codex.nim-codex.blockchain-image=${{ env.CONTRACT_IMAGE }}" >> $GITHUB_ENV
138143
fi
139144
140145
- name: Docker - Meta
@@ -189,35 +194,35 @@ jobs:
189194
runs-on: ubuntu-latest
190195
outputs:
191196
version: ${{ steps.meta.outputs.version }}
197+
codex_image: ${{ steps.image_tag.outputs.codex_image }}
192198
needs: [build, compute]
193199
steps:
194-
195200
- name: Docker - Variables
196201
run: |
197-
# Adjust custom suffix when set and
202+
# Adjust custom suffix when set
198203
if [[ -n "${{ env.TAG_SUFFIX }}" ]]; then
199-
echo "TAG_SUFFIX=-${{ env.TAG_SUFFIX }}" >>$GITHUB_ENV
204+
echo "TAG_SUFFIX=-${{ env.TAG_SUFFIX }}" >> $GITHUB_ENV
200205
fi
201206
# Disable SHA tags on tagged release
202207
if [[ ${{ startsWith(github.ref, 'refs/tags/') }} == "true" ]]; then
203-
echo "TAG_SHA=false" >>$GITHUB_ENV
208+
echo "TAG_SHA=false" >> $GITHUB_ENV
204209
fi
205210
# Handle latest and latest-custom using raw
206211
if [[ ${{ env.TAG_SHA }} == "false" ]]; then
207-
echo "TAG_LATEST=false" >>$GITHUB_ENV
208-
echo "TAG_RAW=true" >>$GITHUB_ENV
212+
echo "TAG_LATEST=false" >> $GITHUB_ENV
213+
echo "TAG_RAW=true" >> $GITHUB_ENV
209214
if [[ -z "${{ env.TAG_SUFFIX }}" ]]; then
210-
echo "TAG_RAW_VALUE=latest" >>$GITHUB_ENV
215+
echo "TAG_RAW_VALUE=latest" >> $GITHUB_ENV
211216
else
212-
echo "TAG_RAW_VALUE=latest-{{ env.TAG_SUFFIX }}" >>$GITHUB_ENV
217+
echo "TAG_RAW_VALUE=latest-{{ env.TAG_SUFFIX }}" >> $GITHUB_ENV
213218
fi
214219
else
215-
echo "TAG_RAW=false" >>$GITHUB_ENV
220+
echo "TAG_RAW=false" >> $GITHUB_ENV
216221
fi
217222
218223
# Create contract label for compatible contract image if specified
219224
if [[ -n "${{ env.CONTRACT_IMAGE }}" ]]; then
220-
echo "CONTRACT_LABEL=storage.codex.nim-codex.blockchain-image=${{ env.CONTRACT_IMAGE }}" >>$GITHUB_ENV
225+
echo "CONTRACT_LABEL=storage.codex.nim-codex.blockchain-image=${{ env.CONTRACT_IMAGE }}" >> $GITHUB_ENV
221226
fi
222227
223228
- name: Docker - Download digests
@@ -257,9 +262,12 @@ jobs:
257262
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
258263
$(printf '${{ env.DOCKER_REPO }}@sha256:%s ' *)
259264
265+
- name: Docker - Image tag
266+
id: image_tag
267+
run: echo "codex_image=${{ env.DOCKER_REPO }}:${{ steps.meta.outputs.version }}" >> "$GITHUB_OUTPUT"
268+
260269
- name: Docker - Inspect image
261-
run: |
262-
docker buildx imagetools inspect ${{ env.DOCKER_REPO }}:${{ steps.meta.outputs.version }}
270+
run: docker buildx imagetools inspect ${{ steps.image_tag.outputs.codex_image }}
263271

264272

265273
# Compute Tests inputs

0 commit comments

Comments
 (0)