name: Deploy - Devnet on: workflow_dispatch: inputs: codex_image: description: codexstorage/nim-codex:latest-dist-tests required: false type: string workflow_call: inputs: codex_image: description: codexstorage/nim-codex:latest-dist-tests required: true type: string env: CODEX_NAMESPACE: codex TOOLS_NAMESPACE: common KUBE_CONFIG: ${{ secrets.DEVNET_KUBE_CONFIG }} KUBE_VERSION: v1.33.1 CODEX_IMAGE: ${{ inputs.codex_image }} SSH_HOSTS: ${{ secrets.DEVNET_SSH_HOSTS }} SSH_PORT: ${{ secrets.DEVNET_SSH_PORT }} SSH_USERNAME: ${{ secrets.DEVNET_SSH_USERNAME }} SSH_PRIVATE_KEY: ${{ secrets.DEVNET_SSH_KEY }} jobs: deploy-contracts: name: Deploy contracts runs-on: ubuntu-latest steps: - name: Create access token uses: actions/create-github-app-token@v2 id: app-token with: app-id: ${{ secrets.DEPLOYER_APP_ID }} private-key: ${{ secrets.DEPLOYER_PRIVATE_KEY }} repositories: codex-contracts-eth - name: Checkout sources uses: actions/checkout@v4 with: submodules: recursive - name: Get contracts submodule ref id: contracts run: echo "ref=$(git rev-parse HEAD:vendor/codex-contracts-eth)" >> $GITHUB_OUTPUT - name: Deploy smart contracts uses: the-actions-org/workflow-dispatch@v4 with: repo: codex-storage/codex-contracts-eth workflow: devnet-contracts.yml token: ${{ steps.app-token.outputs.token }} wait-for-completion-timeout: 20m wait-for-completion-interval: 20s inputs: '{ "network": "codex_devnet", "contracts_ref": "${{ steps.contracts.outputs.ref }}" }' bootstrap-nodes: name: Bootstrap nodes runs-on: ubuntu-latest needs: deploy-contracts steps: - name: Codex Bootstrap - Update uses: appleboy/ssh-action@v1 with: host: ${{ secrets.DEVNET_SSH_HOSTS }} username: ${{ secrets.DEVNET_SSH_USERNAME }} key: ${{ secrets.DEVNET_SSH_KEY }} port: ${{ secrets.DEVNET_SSH_PORT }} script: /opt/codex/remote-deploy.sh ${{ env.CODEX_IMAGE }} cluster-nodes: name: Cluster nodes runs-on: ubuntu-latest needs: bootstrap-nodes steps: - name: Kubectl - Install ${{ env.KUBE_VERSION }} uses: azure/setup-kubectl@v4 with: version: ${{ env.KUBE_VERSION }} - name: Kubectl - Kubeconfig run: | mkdir -p "${HOME}"/.kube echo "${{ env.KUBE_CONFIG }}" | base64 -d > "${HOME}"/.kube/config - name: Codex Storage - Update run: | for node in {1..5}; do kubectl -n "${{ env.CODEX_NAMESPACE }}" patch statefulset codex-storage-${node} \ --patch '{"spec": {"template": {"spec":{"containers":[{"name": "codex", "image":"${{ env.CODEX_IMAGE }}"}]}}}}' done - name: Codex Validators - Update run: | for node in {1..1}; do kubectl -n "${{ env.CODEX_NAMESPACE }}" patch statefulset codex-validator-${node} \ --patch '{"spec": {"template": {"spec":{"containers":[{"name": "codex", "image":"${{ env.CODEX_IMAGE }}"}]}}}}' done - name: Codex Storage - Status run: | WAIT=300 SECONDS=0 sleep=1 for instance in {1..5}; do while (( SECONDS < WAIT )); do pod=codex-storage-${instance}-1 phase=$(kubectl get pod "${pod}" -n "${{ env.CODEX_NAMESPACE }}" -o jsonpath='{.status.phase}') if [[ "${phase}" == "Running" ]]; then echo "Pod ${pod} is in the ${phase} state" break else echo "Pod ${pod} is in the ${phase} state - Check in ${sleep} second(s) / $((WAIT - SECONDS))" fi sleep "${sleep}" done done - name: Codex Validators - Status run: | WAIT=300 SECONDS=0 sleep=1 for instance in {1..1}; do while (( SECONDS < WAIT )); do pod=codex-validator-${instance}-1 phase=$(kubectl get pod "${pod}" -n "${{ env.CODEX_NAMESPACE }}" -o jsonpath='{.status.phase}') if [[ "${phase}" == "Running" ]]; then echo "Pod ${pod} is in the ${phase} state" break else echo "Pod ${pod} is in the ${phase} state - Check in ${sleep} second(s) / $((WAIT - SECONDS))" fi sleep "${sleep}" done done - name: Tools - Update run: | crawler_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app.kubernetes.io/name=crawler' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true) discordbot_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app=discordbot' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true) for pod in "${crawler_pod}" "${discordbot_pod}"; do if [[ -n "${pod}" ]]; then kubectl delete pod -n "${{ env.TOOLS_NAMESPACE }}" "${pod}" --grace-period=10 fi done - name: Tools - Status run: | WAIT=300 SECONDS=0 sleep=1 crawler_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app.kubernetes.io/name=crawler' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true) discordbot_pod=$(kubectl get pod -n "${{ env.TOOLS_NAMESPACE }}" -l 'app=discordbot' -ojsonpath='{.items[0].metadata.name}' 2>/dev/null || true) for pod in "${crawler_pod}" "${discordbot_pod}"; do if [[ -n "${pod}" ]]; then while (( SECONDS < WAIT )); do phase=$(kubectl get pod "${pod}" -n "${{ env.TOOLS_NAMESPACE }}" -o jsonpath='{.status.phase}') if [[ "${phase}" == "Running" ]]; then echo "Pod ${pod} is in the ${phase} state" break else echo "Pod ${pod} is in the ${phase} state - Check in ${sleep} second(s) / $((WAIT - SECONDS))" fi sleep "${sleep}" done fi done