Deploy: ENSNode to Blue/Green Environment on Railway platform #16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: "Deploy: ENSNode to Blue/Green Environment on Railway platform" | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| target: | |
| description: "Target environment (green or blue)" | |
| required: true | |
| type: choice | |
| options: | |
| - green | |
| - blue | |
| tag: | |
| description: "Docker Image Tag (also used for schema name generation)" | |
| required: true | |
| type: string | |
| permissions: | |
| id-token: write | |
| contents: read | |
| jobs: | |
| deploy-environment: | |
| runs-on: blacksmith-4vcpu-ubuntu-2204 | |
| env: | |
| TARGET_ENVIRONMENT: ${{ inputs.target }} | |
| TAG: ${{ inputs.tag }} | |
| ENSINDEXER_DOCKER_IMAGE: "ghcr.io/namehash/ensnode/ensindexer:${{ inputs.tag }}" | |
| ENSAPI_DOCKER_IMAGE: "ghcr.io/namehash/ensnode/ensapi:${{ inputs.tag }}" | |
| ENSRAINBOW_DOCKER_IMAGE: "ghcr.io/namehash/ensnode/ensrainbow:${{ inputs.tag }}" | |
| ENSADMIN_DOCKER_IMAGE: "ghcr.io/namehash/ensnode/ensadmin:${{ inputs.tag }}" | |
| RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} | |
| RAILWAY_PROJECT_ID: ${{ secrets.RAILWAY_PROJECT_ID }} | |
| RAILWAY_ENVIRONMENT_ID: ${{ secrets.RAILWAY_ENVIRONMENT_ID}} | |
| RAILWAY_TEAM_TOKEN: ${{ secrets.RAILWAY_TEAM_TOKEN }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| - name: Check if Docker images exists | |
| run: | | |
| docker manifest inspect ${{ env.ENSINDEXER_DOCKER_IMAGE }} || { echo "Given docker image does not exist: ${{ env.ENSINDEXER_DOCKER_IMAGE }}"; exit 1; } | |
| docker manifest inspect ${{ env.ENSAPI_DOCKER_IMAGE }} || { echo "Given docker image does not exist: ${{ env.ENSAPI_DOCKER_IMAGE }}"; exit 1; } | |
| docker manifest inspect ${{ env.ENSRAINBOW_DOCKER_IMAGE }} || { echo "Given docker image does not exist: ${{ env.ENSRAINBOW_DOCKER_IMAGE }}"; exit 1; } | |
| docker manifest inspect ${{ env.ENSADMIN_DOCKER_IMAGE }} || { echo "Given docker image does not exist: ${{ env.ENSADMIN_DOCKER_IMAGE }}"; exit 1; } | |
| - name: Print switch target | |
| run: | | |
| echo "Deploying on: $TARGET_ENVIRONMENT" | |
| - name: Calculate env variables | |
| run: | | |
| case "$TARGET_ENVIRONMENT" in | |
| "green") | |
| #ENVIRONMENT | |
| echo "RAILWAY_ENVIRONMENT_ID=${{ secrets.GREEN_RAILWAY_ENVIRONMENT_ID }}" >> $GITHUB_ENV | |
| #ALPHA | |
| echo "ALPHA_API_SVC_ID="${{ secrets.GREEN_ALPHA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "ALPHA_INDEXER_SVC_ID="${{ secrets.GREEN_ALPHA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #MAINNET | |
| echo "MAINNET_API_SVC_ID="${{ secrets.GREEN_MAINNET_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "MAINNET_INDEXER_SVC_ID="${{ secrets.GREEN_MAINNET_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #ALPHA-SEPOLIA | |
| echo "ALPHA_SEPOLIA_API_SVC_ID="${{ secrets.GREEN_ALPHA_SEPOLIA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "ALPHA_SEPOLIA_INDEXER_SVC_ID="${{ secrets.GREEN_ALPHA_SEPOLIA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #V2-SEPOLIA | |
| echo "V2_SEPOLIA_API_SVC_ID="${{ secrets.GREEN_V2_SEPOLIA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "V2_SEPOLIA_INDEXER_SVC_ID="${{ secrets.GREEN_V2_SEPOLIA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #SEPOLIA | |
| echo "SEPOLIA_API_SVC_ID="${{ secrets.GREEN_SEPOLIA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "SEPOLIA_INDEXER_SVC_ID="${{ secrets.GREEN_SEPOLIA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #ENSRAINBOW | |
| echo "ENSRAINBOW_SVC_ID="${{ secrets.GREEN_ENSRAINBOW_SVC_ID }} >> "$GITHUB_ENV" | |
| #ENSRAINBOW SEARCHLIGHT | |
| echo "ENSRAINBOW_SEARCHLIGHT_SVC_ID="${{ secrets.GREEN_ENSRAINBOW_SEARCHLIGHT_SVC_ID }} >> "$GITHUB_ENV" | |
| #ENSADMIN | |
| echo "ENSADMIN_SVC_ID="${{ secrets.GREEN_ENSADMIN_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "SLACK_TITLE=':large_green_circle: GREEN environment is now having new ENSNode version - '"${{ env.TAG }} >> "$GITHUB_ENV" | |
| ;; | |
| "blue") | |
| #ENVIRONMENT | |
| echo "RAILWAY_ENVIRONMENT_ID=${{ secrets.BLUE_RAILWAY_ENVIRONMENT_ID }}" >> $GITHUB_ENV | |
| #ALPHA | |
| echo "ALPHA_API_SVC_ID="${{ secrets.BLUE_ALPHA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "ALPHA_INDEXER_SVC_ID="${{ secrets.BLUE_ALPHA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #MAINNET | |
| echo "MAINNET_API_SVC_ID="${{ secrets.BLUE_MAINNET_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "MAINNET_INDEXER_SVC_ID="${{ secrets.BLUE_MAINNET_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #ALPHA-SEPOLIA | |
| echo "ALPHA_SEPOLIA_API_SVC_ID="${{ secrets.BLUE_ALPHA_SEPOLIA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "ALPHA_SEPOLIA_INDEXER_SVC_ID="${{ secrets.BLUE_ALPHA_SEPOLIA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #V2-SEPOLIA | |
| echo "V2_SEPOLIA_API_SVC_ID="${{ secrets.BLUE_V2_SEPOLIA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "V2_SEPOLIA_INDEXER_SVC_ID="${{ secrets.BLUE_V2_SEPOLIA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #SEPOLIA | |
| echo "SEPOLIA_API_SVC_ID="${{ secrets.BLUE_SEPOLIA_API_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "SEPOLIA_INDEXER_SVC_ID="${{ secrets.BLUE_SEPOLIA_INDEXER_SVC_ID }} >> "$GITHUB_ENV" | |
| #ENSRAINBOW | |
| echo "ENSRAINBOW_SVC_ID="${{ secrets.BLUE_ENSRAINBOW_SVC_ID }} >> "$GITHUB_ENV" | |
| #ENSRAINBOW SEARCHLIGHT | |
| echo "ENSRAINBOW_SEARCHLIGHT_SVC_ID="${{ secrets.BLUE_ENSRAINBOW_SEARCHLIGHT_SVC_ID }} >> "$GITHUB_ENV" | |
| #ENSADMIN | |
| echo "ENSADMIN_SVC_ID="${{ secrets.BLUE_ENSADMIN_SVC_ID }} >> "$GITHUB_ENV" | |
| echo "SLACK_TITLE=':large_blue_circle: BLUE environment is now having new ENSNode version - '"${{ env.TAG }} >> "$GITHUB_ENV" | |
| ;; | |
| *) | |
| echo "Environment not recognized, skipping workflow" | |
| exit 1 | |
| esac | |
| # Update indexer source docker image | |
| - name: Update shared environment variable | |
| run: | | |
| update_service_image() { | |
| local environment_id=$1 | |
| local service_id=$2 | |
| local docker_image=$3 | |
| echo "Updating service $service_id" | |
| curl --request POST \ | |
| --silent \ | |
| --fail \ | |
| --url https://backboard.railway.app/graphql/v2 \ | |
| --header 'Authorization: Bearer '${{ env.RAILWAY_TOKEN }} \ | |
| --header 'Content-Type: application/json' \ | |
| --data '{ | |
| "query": "mutation serviceInstanceUpdate($environmentId: String, $input: ServiceInstanceUpdateInput!, $serviceId: String!) { serviceInstanceUpdate(environmentId: $environmentId input: $input serviceId: $serviceId) }", | |
| "variables": { | |
| "environmentId": "'$environment_id'", | |
| "input": {"source": {"image": "'$docker_image'"}}, | |
| "serviceId": "'$service_id'" | |
| } | |
| }' | |
| echo "Finished updating $service_id" | |
| } | |
| #ALPHA | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_API_SVC_ID} ${{ env.ENSAPI_DOCKER_IMAGE }} | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_INDEXER_SVC_ID} ${{ env.ENSINDEXER_DOCKER_IMAGE }} | |
| #MAINNET | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${MAINNET_API_SVC_ID} ${{ env.ENSAPI_DOCKER_IMAGE }} | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${MAINNET_INDEXER_SVC_ID} ${{ env.ENSINDEXER_DOCKER_IMAGE }} | |
| #ALPHA-SEPOLIA | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_SEPOLIA_API_SVC_ID} ${{ env.ENSAPI_DOCKER_IMAGE }} | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_SEPOLIA_INDEXER_SVC_ID} ${{ env.ENSINDEXER_DOCKER_IMAGE }} | |
| #V2-SEPOLIA | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${V2_SEPOLIA_API_SVC_ID} ${{ env.ENSAPI_DOCKER_IMAGE }} | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${V2_SEPOLIA_INDEXER_SVC_ID} ${{ env.ENSINDEXER_DOCKER_IMAGE }} | |
| #SEPOLIA | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${SEPOLIA_API_SVC_ID} ${{ env.ENSAPI_DOCKER_IMAGE }} | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${SEPOLIA_INDEXER_SVC_ID} ${{ env.ENSINDEXER_DOCKER_IMAGE }} | |
| #ENSRAINBOW | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ENSRAINBOW_SVC_ID} ${{ env.ENSRAINBOW_DOCKER_IMAGE }} | |
| #ENSRAINBOW SEARCHLIGHT | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ENSRAINBOW_SEARCHLIGHT_SVC_ID} ${{ env.ENSRAINBOW_DOCKER_IMAGE }} | |
| #ENSADMIN | |
| update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ENSADMIN_SVC_ID} ${{ env.ENSADMIN_DOCKER_IMAGE }} | |
| # Update ENSINDEXER_SCHEMA_NAME for each indexer based on input tag | |
| - name: Update shared environment variable | |
| run: | | |
| set_shared_variable() { | |
| local environment_id=$1 | |
| local variable_name=$2 | |
| local variable_value=$3 | |
| echo "Setting $variable_name" | |
| curl --request POST \ | |
| --silent \ | |
| --fail \ | |
| --url https://backboard.railway.app/graphql/v2 \ | |
| --header 'Authorization: Bearer '${{ env.RAILWAY_TOKEN }} \ | |
| --header 'Content-Type: application/json' \ | |
| --data '{"query": "mutation variableUpsert { variableUpsert(input: { projectId: \"'${{ env.RAILWAY_PROJECT_ID }}'\", environmentId: \"'${environment_id}'\", name: \"'${variable_name}'\", value: \"'${variable_value}'\" }) }"}' | |
| echo "Finished setting $variable_name" | |
| } | |
| set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA_ENSINDEXER_SCHEMA_NAME" "alphaSchema${TAG}" | |
| set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "MAINNET_ENSINDEXER_SCHEMA_NAME" "mainnetSchema${TAG}" | |
| set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA-SEPOLIA_ENSINDEXER_SCHEMA_NAME" "alphaSepoliaSchema${TAG}" | |
| set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "V2-SEPOLIA_ENSINDEXER_SCHEMA_NAME" "v2SepoliaSchema${TAG}" | |
| set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "SEPOLIA_ENSINDEXER_SCHEMA_NAME" "sepoliaSchema${TAG}" | |
| - name: Redeploy ENSNode instances | |
| run: | | |
| redeploy_service() { | |
| local environment_id=$1 | |
| local service_id=$2 | |
| echo "Redeploying $service_id" | |
| curl --request POST \ | |
| --silent \ | |
| --url https://backboard.railway.app/graphql/v2 \ | |
| --header 'Authorization: Bearer '${{ env.RAILWAY_TOKEN }} \ | |
| --header 'Content-Type: application/json' \ | |
| --data "{\"query\":\"mutation serviceInstanceDeploy(\$serviceId: String!, \$environmentId: String!) { serviceInstanceDeploy(serviceId: \$serviceId, environmentId: \$environmentId) }\",\"variables\":{\"environmentId\":\"${environment_id}\",\"serviceId\":\"${service_id}\"}}" | |
| echo "Finished redeploying $service_id" | |
| } | |
| #ALPHA | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_API_SVC_ID} | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_INDEXER_SVC_ID} | |
| #MAINNET | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${MAINNET_API_SVC_ID} | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${MAINNET_INDEXER_SVC_ID} | |
| #ALPHA-SEPOLIA | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_SEPOLIA_API_SVC_ID} | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${ALPHA_SEPOLIA_INDEXER_SVC_ID} | |
| #V2-SEPOLIA | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${V2_SEPOLIA_API_SVC_ID} | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${V2_SEPOLIA_INDEXER_SVC_ID} | |
| #SEPOLIA | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${SEPOLIA_API_SVC_ID} | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${SEPOLIA_INDEXER_SVC_ID} | |
| #ENSRAINBOW | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${ENSRAINBOW_SVC_ID} | |
| #ENSRAINBOW SEARCHLIGHT | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${ENSRAINBOW_SEARCHLIGHT_SVC_ID} | |
| #ENSADMIN | |
| redeploy_service ${RAILWAY_ENVIRONMENT_ID} ${ENSADMIN_SVC_ID} | |
| - uses: ./.github/actions/send_slack_notification | |
| with: | |
| slack_webhook: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| slack_title: ${{ env.SLACK_TITLE }} | |
| slack_message: "✅ Deploy ENSNode completed" |