Deploy #7
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 | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: Git ref to deploy | |
| required: false | |
| default: main | |
| railway_environment: | |
| description: Railway environment name or ID | |
| required: false | |
| default: production | |
| app_base_url: | |
| description: Public HTTPS base URL used for smoke validation | |
| required: false | |
| default: "" | |
| concurrency: | |
| group: deploy-production | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| deploy: | |
| name: deploy | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| environment: | |
| name: production | |
| env: | |
| RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} | |
| RAILWAY_PROJECT_ID: ${{ secrets.RAILWAY_PROJECT_ID }} | |
| RAILWAY_SERVICE: ${{ secrets.RAILWAY_SERVICE }} | |
| RAILWAY_ENVIRONMENT: ${{ github.event_name == 'workflow_dispatch' && inputs.railway_environment || secrets.RAILWAY_ENVIRONMENT }} | |
| APP_BASE_URL: ${{ github.event_name == 'workflow_dispatch' && inputs.app_base_url || secrets.RAILWAY_PUBLIC_URL }} | |
| steps: | |
| - name: Validate deployment configuration | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| required_secrets=( | |
| RAILWAY_TOKEN | |
| RAILWAY_PROJECT_ID | |
| RAILWAY_SERVICE | |
| ) | |
| for key in "${required_secrets[@]}"; do | |
| if [ -z "${!key:-}" ]; then | |
| echo "::error::Missing required repository secret: ${key}" | |
| exit 1 | |
| fi | |
| done | |
| if [ -z "${RAILWAY_ENVIRONMENT:-}" ]; then | |
| echo "RAILWAY_ENVIRONMENT=production" >> "${GITHUB_ENV}" | |
| fi | |
| if [ -z "${APP_BASE_URL:-}" ]; then | |
| echo "SMOKE_ENABLED=false" >> "${GITHUB_ENV}" | |
| echo "::warning::RAILWAY_PUBLIC_URL is not configured. Deployment will run, but smoke validation will be skipped." | |
| else | |
| case "${APP_BASE_URL}" in | |
| https://*) | |
| ;; | |
| *) | |
| echo "::error::RAILWAY_PUBLIC_URL/app_base_url must be a full HTTPS base URL, for example https://auth-api-production.up.railway.app" | |
| exit 1 | |
| ;; | |
| esac | |
| echo "SMOKE_ENABLED=true" >> "${GITHUB_ENV}" | |
| fi | |
| - name: Checkout source | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.event.release.tag_name }} | |
| - name: Use Node.js 20 | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Install Railway CLI | |
| run: npm install --global @railway/cli@latest | |
| - name: Deploy to Railway | |
| env: | |
| CI: "" | |
| run: railway up --project "$RAILWAY_PROJECT_ID" --service "$RAILWAY_SERVICE" --environment "${RAILWAY_ENVIRONMENT:-production}" | |
| - name: Run smoke validation | |
| if: env.SMOKE_ENABLED == 'true' | |
| run: ./scripts/smoke-production.sh "$APP_BASE_URL" | |
| - name: Write deployment summary | |
| shell: bash | |
| run: | | |
| { | |
| echo "## Deployment summary" | |
| echo | |
| echo "- Trigger: ${GITHUB_EVENT_NAME}" | |
| echo "- Ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.event.release.tag_name }}" | |
| echo "- Railway environment: ${RAILWAY_ENVIRONMENT:-production}" | |
| if [ -n "${APP_BASE_URL:-}" ]; then | |
| echo "- Base URL: ${APP_BASE_URL}" | |
| echo "- Health: ${APP_BASE_URL%/}/health" | |
| echo "- Readiness: ${APP_BASE_URL%/}/ready" | |
| echo "- OpenAPI: ${APP_BASE_URL%/}/docs.json" | |
| else | |
| echo "- Base URL: not configured" | |
| fi | |
| } >> "${GITHUB_STEP_SUMMARY}" |