Setup minimal CI #12
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: Build and push Docker image | |
| on: | |
| push: | |
| branches: ["main", "release"] | |
| jobs: | |
| docker: | |
| name: Build and push Docker image | |
| runs-on: ubuntu-latest | |
| env: | |
| AWS_REGION: us-east-1 | |
| ECR_REGISTRY: 336594912921.dkr.ecr.us-east-1.amazonaws.com | |
| APP_NAME: rpc-proxy | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # needed for git describe to find tags | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| aws-access-key-id: ${{ secrets.ECR_AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.ECR_AWS_SECRET_ACCESS_KEY }} | |
| aws-region: ${{ env.AWS_REGION }} | |
| - name: Login to Amazon ECR | |
| id: login-ecr | |
| uses: aws-actions/amazon-ecr-login@v2 | |
| - name: Set image metadata | |
| id: meta | |
| run: | | |
| SHORT_SHA=${GITHUB_SHA:0:7} | |
| # Derive version from the nearest upstream tag (e.g. 0.0.62-2-g2fe6ca3) | |
| BASE_VERSION=$(git describe --tags --always) | |
| VERSION="custom-${BASE_VERSION}" | |
| if [[ "$GITHUB_REF_NAME" == "main" ]]; then | |
| TAGS="dev latest" | |
| DEPLOYMENT_ENV="dev" | |
| elif [[ "$GITHUB_REF_NAME" == "release" ]]; then | |
| TAGS="prod" | |
| DEPLOYMENT_ENV="prod" | |
| else | |
| # Use branch name as tag, sanitized for Docker tag format | |
| TAGS=$(echo "$GITHUB_REF_NAME" | sed 's/[^a-zA-Z0-9._-]/-/g') | |
| DEPLOYMENT_ENV="" | |
| fi | |
| # Build full Docker tags (registry/app:tag) for each tag + short SHA | |
| DOCKER_TAGS="" | |
| for T in $TAGS $SHORT_SHA; do | |
| DOCKER_TAGS="${DOCKER_TAGS}${ECR_REGISTRY}/${APP_NAME}:${T}"$'\n' | |
| done | |
| echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT" | |
| echo "tags=$TAGS" >> "$GITHUB_OUTPUT" | |
| echo "deployment_env=$DEPLOYMENT_ENV" >> "$GITHUB_OUTPUT" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "docker_tags<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$DOCKER_TAGS" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| echo "Image version: $VERSION (tags: $TAGS)" | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build and push image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.docker_tags }} | |
| build-args: | | |
| VERSION=${{ steps.meta.outputs.version }} | |
| COMMIT_SHA=${{ steps.meta.outputs.short_sha }} | |
| cache-from: type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.APP_NAME }}:cache | |
| cache-to: type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.APP_NAME }}:cache,mode=max | |
| - name: Promote image via infra workflow | |
| if: ${{ steps.meta.outputs.deployment_env != '' }} | |
| env: | |
| GH_TOKEN: ${{ secrets.INFRA_WORKFLOW_PAT }} | |
| GH_WORKFLOW_OWNER: rhinestonewtf | |
| GH_WORKFLOW_REPO: infra | |
| WORKFLOW_FILE: aws-promote-app-version.yaml | |
| DEPLOYMENT_ENV: ${{ steps.meta.outputs.deployment_env }} | |
| SHORT_SHA: ${{ steps.meta.outputs.short_sha }} | |
| run: | | |
| set -euo pipefail | |
| if [[ -z "${GH_TOKEN:-}" ]]; then | |
| echo "INFRA_WORKFLOW_PAT secret is not configured" >&2 | |
| exit 1 | |
| fi | |
| TARGET_REF="main" | |
| WORKFLOW_PATH=".github/workflows/$WORKFLOW_FILE" | |
| WORKFLOW_METADATA=$(gh api repos/$GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO/actions/workflows/$WORKFLOW_FILE) | |
| WORKFLOW_ID=$(echo "$WORKFLOW_METADATA" | jq -r '.id // empty') | |
| if [[ -z "$WORKFLOW_ID" ]]; then | |
| echo "Unable to resolve workflow id for $WORKFLOW_PATH" >&2 | |
| exit 1 | |
| fi | |
| echo "Dispatching $WORKFLOW_FILE (id: $WORKFLOW_ID) in $GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO for env $DEPLOYMENT_ENV (version $SHORT_SHA)" | |
| API_ROOT="https://api.github.com" | |
| DISPATCH_URL="$API_ROOT/repos/$GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO/actions/workflows/$WORKFLOW_FILE/dispatches" | |
| AUTH_HEADER=( | |
| -H "Authorization: Bearer $GH_TOKEN" | |
| -H "Accept: application/vnd.github+json" | |
| -H "Content-Type: application/json" | |
| ) | |
| DISPATCH_BODY=$(jq -n \ | |
| --arg ref "$TARGET_REF" \ | |
| --arg env "$DEPLOYMENT_ENV" \ | |
| --arg app "$APP_NAME" \ | |
| --arg sha "$SHORT_SHA" \ | |
| '{ref: $ref, inputs: {env: $env, app_name: $app, version_sha: $sha}}') | |
| DISPATCH_STATUS=$(curl -sS -o /tmp/dispatch.json -w "%{http_code}" "${AUTH_HEADER[@]}" \ | |
| -X POST "$DISPATCH_URL" \ | |
| -d "$DISPATCH_BODY") | |
| if [[ "$DISPATCH_STATUS" -ge 300 ]]; then | |
| echo "Failed to dispatch remote workflow (status $DISPATCH_STATUS)" >&2 | |
| cat /tmp/dispatch.json >&2 || true | |
| exit 1 | |
| fi | |
| echo "Awaiting workflow run to be created..." | |
| sleep 10 | |
| RUN_ID=$(gh api https://api.github.com/repos/$GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO/actions/runs --jq '[.workflow_runs[] | select(.event == "workflow_dispatch")][0].id' | sed 's/\x1b\[[0-9;]*m//g') | |
| echo "Run ID: $RUN_ID" | |
| if [[ -z "$RUN_ID" ]]; then | |
| echo "Failed to find the dispatched workflow run" >&2 | |
| exit 1 | |
| fi | |
| gh run watch "$RUN_ID" --repo $GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO --exit-status --compact --interval 15 | |
| - name: Notify Slack of deployment | |
| if: ${{ success() && steps.meta.outputs.deployment_env != '' }} | |
| env: | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
| run: | | |
| if [[ -z "${SLACK_WEBHOOK:-}" ]]; then | |
| echo "SLACK_WEBHOOK secret is not configured" >&2 | |
| exit 1 | |
| fi | |
| MESSAGE=$(jq -n \ | |
| --arg text ":rocket: App *${{ env.APP_NAME }}* is live on *${{ steps.meta.outputs.deployment_env }}* version: *${{ steps.meta.outputs.short_sha }}*" \ | |
| '{text: $text}') | |
| curl -sSf -X POST -H 'Content-type: application/json' --data "$MESSAGE" "$SLACK_WEBHOOK" |