Created
January 17, 2026 18:14
-
-
Save Ba4bes/6e0f38b77674ee7d28bab5c4049db53a to your computer and use it in GitHub Desktop.
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
| # =================================================================== | |
| # GitHub Actions Workflow for Astro + Azure Static Web Apps | |
| # =================================================================== | |
| # This workflow automates building, testing, and deploying an Astro | |
| # site to Azure Static Web Apps with infrastructure as code. | |
| # | |
| # Prerequisites: | |
| # 1. Azure subscription with a Service Principal configured for OIDC | |
| # 2. GitHub secrets configured (see "Required Secrets" section below) | |
| # 3. Bicep template for infrastructure (optional, see deploy_infrastructure job) | |
| # 4. Package manager: pnpm (can be changed to npm/yarn if needed) | |
| # | |
| # Required GitHub Secrets: | |
| # - AZURE_CLIENT_ID: Service Principal Application (client) ID | |
| # - AZURE_TENANT_ID: Azure AD Tenant ID | |
| # - AZURE_SUBSCRIPTION_ID: Azure Subscription ID | |
| # - AZURE_RG_NAME: Azure Resource Group name | |
| # | |
| # For OIDC setup instructions, see: | |
| # https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure | |
| # =================================================================== | |
| name: Build and Deploy | |
| # Trigger conditions for this workflow | |
| on: | |
| push: | |
| branches: | |
| - main # Deploy to production when code is merged to main | |
| pull_request: | |
| types: [opened, synchronize, reopened, closed] | |
| branches: | |
| - main # Create preview deployments for PRs | |
| schedule: | |
| # Optional: Daily rebuild to refresh dynamic content (e.g., from APIs) | |
| # Remove this if your site is purely static | |
| - cron: '0 6 * * *' # Runs at 6:00 AM UTC daily | |
| workflow_dispatch: # Allow manual triggering from GitHub UI | |
| # Permissions required for OIDC authentication and PR comments | |
| permissions: | |
| id-token: write # Required for OIDC authentication with Azure | |
| contents: read # Required to checkout code (default permission) | |
| pull-requests: write # Required to post preview URLs as PR comments | |
| # Environment variables used across all jobs | |
| # Customize these for your project | |
| env: | |
| OUTPUT_LOCATION: 'dist' # Astro's default build output directory | |
| STATIC_WEB_APP_NAME: 'swa-website' # Change to your SWA name | |
| NODE_VERSION: '20' # Node.js version for your project | |
| PNPM_VERSION: '9' # pnpm version (change to npm/yarn if needed) | |
| jobs: | |
| # =================================================================== | |
| # Job 1: Build and Test | |
| # =================================================================== | |
| # This job builds your Astro site and runs tests to ensure code quality | |
| # before deployment. The build artifact is uploaded for use in later jobs. | |
| # =================================================================== | |
| build_and_test: | |
| name: Build & Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| # Check out the repository code | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # Setup pnpm package manager | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: ${{ env.PNPM_VERSION }} | |
| # Setup Node.js with caching for faster subsequent runs | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'pnpm' # Change to 'npm' or 'yarn' if using those | |
| # Install project dependencies | |
| # --frozen-lockfile ensures reproducible builds | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # Run test suite to catch bugs before deployment | |
| # Remove this step if you don't have tests configured | |
| - name: Run tests | |
| run: pnpm test:run | |
| # Build the Astro site | |
| # This creates optimized static files in the dist/ directory | |
| - name: Build Astro site | |
| run: pnpm build | |
| # Upload build artifacts for deployment jobs | |
| # This allows us to reuse the build across multiple deployment environments | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.OUTPUT_LOCATION }} | |
| path: ${{ env.OUTPUT_LOCATION }}/ | |
| # =================================================================== | |
| # Job 2: Deploy Infrastructure (Optional) | |
| # =================================================================== | |
| # This job deploys Azure infrastructure using Bicep (Infrastructure as Code). | |
| # It creates or updates the Static Web App resource in Azure. | |
| # | |
| # Optional: If your Static Web App is already created manually in Azure Portal, | |
| # you can remove this entire job and skip to deploy_preview/deploy_production. | |
| # Just make sure to set STATIC_WEB_APP_NAME env variable to match your existing resource. | |
| # =================================================================== | |
| deploy_infrastructure: | |
| name: Deploy Infrastructure | |
| runs-on: ubuntu-latest | |
| needs: build_and_test # Only runs after successful build | |
| # Run for pushes to main, scheduled runs, manual triggers, and PRs | |
| if: github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' | |
| outputs: | |
| # Output values that other jobs can reference | |
| static_web_app_name: ${{ steps.deploy-bicep.outputs.staticWebAppName }} | |
| default_hostname: ${{ steps.get-hostname.outputs.hostname }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # Authenticate to Azure using OIDC (OpenID Connect) | |
| # This is more secure than using a Service Principal secret | |
| - name: Azure Login (OIDC) | |
| uses: azure/login@v2 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| # Deploy Bicep template to create/update Azure Static Web App | |
| # Your Bicep file should be at ./infra/main.bicep | |
| # Customize the template path if your structure is different | |
| - name: Deploy Bicep Template | |
| id: deploy-bicep | |
| uses: azure/arm-deploy@v2 | |
| with: | |
| resourceGroupName: ${{ secrets.AZURE_RG_NAME }} | |
| template: ./infra/main.bicep | |
| failOnStdErr: false | |
| # Retrieve the Static Web App's hostname for preview URL generation | |
| - name: Get Static Web App Hostname | |
| id: get-hostname | |
| run: | | |
| HOSTNAME=$(az staticwebapp show \ | |
| --name ${{ env.STATIC_WEB_APP_NAME }} \ | |
| --resource-group ${{ secrets.AZURE_RG_NAME }} \ | |
| --query "defaultHostname" -o tsv) | |
| echo "hostname=$HOSTNAME" >> $GITHUB_OUTPUT | |
| # =================================================================== | |
| # Job 3: Deploy to Preview Environment | |
| # =================================================================== | |
| # This job deploys your Astro site to a preview environment when a PR | |
| # is opened or updated. Each PR gets its own isolated preview URL. | |
| # =================================================================== | |
| deploy_preview: | |
| name: Deploy to Preview | |
| runs-on: ubuntu-latest | |
| needs: deploy_infrastructure # Requires infrastructure to be deployed first | |
| # Only run for PR events (opened, synchronized, or reopened) | |
| if: github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened') | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # Download the build artifact created in the build_and_test job | |
| # This avoids rebuilding the site in each deployment job | |
| - name: Download build artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ env.OUTPUT_LOCATION }} | |
| path: ${{ env.OUTPUT_LOCATION }}/ | |
| # Authenticate to Azure for deployment | |
| - name: Azure Login (OIDC) | |
| uses: azure/login@v2 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| # Install the Azure Static Web Apps CLI for deployment | |
| - name: Install SWA CLI | |
| run: npm install -g @azure/static-web-apps-cli | |
| # Deploy the built site to a preview environment | |
| # SWA automatically creates a preview environment for each PR | |
| - name: Deploy to Preview Environment | |
| run: | | |
| swa deploy ${{ env.OUTPUT_LOCATION }} \ | |
| --resource-group ${{ secrets.AZURE_RG_NAME }} \ | |
| --app-name ${{ env.STATIC_WEB_APP_NAME }} | |
| # Generate the preview URL for this PR | |
| # Azure SWA preview URLs follow the pattern: https://{base}-{pr-number}.{region}.azurestaticapps.net | |
| - name: Get Preview URL | |
| id: preview-url | |
| run: | | |
| DEFAULT_HOSTNAME="${{ needs.deploy_infrastructure.outputs.default_hostname }}" | |
| PR_NUMBER="${{ github.event.pull_request.number }}" | |
| # Extract the base domain and construct preview URL | |
| PREVIEW_URL=$(echo "$DEFAULT_HOSTNAME" | sed "s/^/https:\/\//" | sed "s/\./-${PR_NUMBER}./") | |
| echo "preview_url=$PREVIEW_URL" >> $GITHUB_OUTPUT | |
| echo "### Preview Deployment" >> $GITHUB_STEP_SUMMARY | |
| echo "Preview URL: $PREVIEW_URL" >> $GITHUB_STEP_SUMMARY | |
| # Post a comment on the PR with the preview URL | |
| # This makes it easy for reviewers to see the live preview | |
| - name: Comment Preview URL on PR | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const previewUrl = '${{ steps.preview-url.outputs.preview_url }}'; | |
| const comment = `**Preview deployment completed!** | |
| **Preview URL:** ${previewUrl} | |
| _Note: The preview environment is automatically created for this pull request._ | |
| **Next steps:** | |
| - Review your changes at the preview URL | |
| - Get your PR reviewed and approved | |
| - Merge this PR to automatically deploy to production`; | |
| github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.payload.pull_request.number, | |
| body: comment | |
| }); | |
| # =================================================================== | |
| # Job 4: Deploy to Production | |
| # =================================================================== | |
| # This job deploys your Astro site to the production environment. | |
| # It runs when code is merged to main, on scheduled runs, or manual triggers. | |
| # =================================================================== | |
| deploy_production: | |
| name: Deploy to Production | |
| runs-on: ubuntu-latest | |
| needs: deploy_infrastructure # Requires infrastructure to be deployed first | |
| # Only run for main branch pushes, scheduled runs, or manual triggers | |
| if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # Download the build artifact created in the build_and_test job | |
| - name: Download build artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ env.OUTPUT_LOCATION }} | |
| path: ${{ env.OUTPUT_LOCATION }}/ | |
| # Authenticate to Azure for production deployment | |
| - name: Azure Login (OIDC) | |
| uses: azure/login@v2 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| # Install the Azure Static Web Apps CLI | |
| - name: Install SWA CLI | |
| run: npm install -g @azure/static-web-apps-cli | |
| # Deploy to the production environment | |
| # The --env production flag ensures deployment to the main production slot | |
| - name: Deploy to Production Environment | |
| run: | | |
| swa deploy ${{ env.OUTPUT_LOCATION }} \ | |
| --resource-group ${{ secrets.AZURE_RG_NAME }} \ | |
| --app-name ${{ env.STATIC_WEB_APP_NAME }} \ | |
| --env production |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment