test branch protection rule #8
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: Node.js CI/CD to Azure | |
| # Teaching example for GitHub Actions with Azure deployment | |
| on: | |
| push: | |
| branches: [ main, master ] | |
| paths: | |
| - 'nodeapp-1/**' | |
| - '.github/workflows/node-azure-deploy.yml' | |
| pull_request: | |
| branches: [ main, master ] | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: 'Environment to deploy to' | |
| required: true | |
| default: 'development' | |
| type: choice | |
| options: | |
| - development | |
| - staging | |
| - production | |
| env: | |
| NODE_VERSION: '18.x' | |
| AZURE_WEBAPP_NAME: 'webapp-az400-demo' | |
| AZURE_WEBAPP_PACKAGE_PATH: './nodeapp-1' | |
| WORKING_DIRECTORY: 'nodeapp-1' | |
| jobs: | |
| # ======================================== | |
| # JOB 1: BUILD AND TEST | |
| # ======================================== | |
| build: | |
| name: Build and Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| - name: 🔧 Setup Node.js ${{ env.NODE_VERSION }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| cache-dependency-path: '${{ env.WORKING_DIRECTORY }}/package-lock.json' | |
| - name: 📦 Install dependencies | |
| run: npm ci | |
| working-directory: ${{ env.WORKING_DIRECTORY }} | |
| - name: 🔒 Security audit | |
| run: npm audit --audit-level=high | |
| working-directory: ${{ env.WORKING_DIRECTORY }} | |
| continue-on-error: true | |
| - name: 🧹 Lint code | |
| run: npm run lint | |
| working-directory: ${{ env.WORKING_DIRECTORY }} | |
| - name: 🧪 Run tests with Mocha | |
| run: npm test | |
| working-directory: ${{ env.WORKING_DIRECTORY }} | |
| - name: 📊 Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: mochawesome-report | |
| path: ${{ env.WORKING_DIRECTORY }}/mochawesome-report | |
| retention-days: 7 | |
| - name: 📤 Upload artifact for deployment | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: node-app | |
| path: ${{ env.WORKING_DIRECTORY }} | |
| retention-days: 5 | |
| # ======================================== | |
| # JOB 2: DEPLOY TO DEVELOPMENT | |
| # ======================================== | |
| deploy-dev: | |
| name: Deploy to Development | |
| runs-on: ubuntu-latest | |
| needs: build | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| environment: | |
| name: development | |
| url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} | |
| steps: | |
| - name: 📥 Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: node-app | |
| path: ./app | |
| - name: 🔐 Login to Azure | |
| uses: azure/login@v1 | |
| with: | |
| creds: ${{ secrets.AZURE_CREDENTIALS }} | |
| - name: 🚀 Deploy to Azure Web App | |
| id: deploy-to-webapp | |
| uses: azure/webapps-deploy@v3 | |
| with: | |
| app-name: ${{ env.AZURE_WEBAPP_NAME }}-dev | |
| package: ./app | |
| startup-command: 'npm start' | |
| - name: 🔥 Smoke test | |
| run: | | |
| sleep 30 | |
| response=$(curl -s -o /dev/null -w "%{http_code}" https://${{ env.AZURE_WEBAPP_NAME }}-dev.azurewebsites.net) | |
| if [ $response -eq 200 ]; then | |
| echo "✅ Smoke test passed!" | |
| else | |
| echo "❌ Smoke test failed with status code: $response" | |
| exit 1 | |
| fi | |
| # ======================================== | |
| # JOB 3: DEPLOY TO STAGING | |
| # ======================================== | |
| deploy-staging: | |
| name: Deploy to Staging | |
| runs-on: ubuntu-latest | |
| needs: deploy-dev | |
| environment: | |
| name: staging | |
| url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} | |
| steps: | |
| - name: 📥 Checkout for tests | |
| uses: actions/checkout@v4 | |
| - name: 📥 Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: node-app | |
| path: ./app | |
| - name: 🔐 Login to Azure | |
| uses: azure/login@v1 | |
| with: | |
| creds: ${{ secrets.AZURE_CREDENTIALS }} | |
| - name: 🚀 Deploy to staging slot | |
| id: deploy-to-webapp | |
| uses: azure/webapps-deploy@v3 | |
| with: | |
| app-name: ${{ env.AZURE_WEBAPP_NAME }} | |
| slot-name: staging | |
| package: ./app | |
| - name: 🧪 Run integration tests | |
| run: | | |
| cd ${{ env.WORKING_DIRECTORY }} | |
| npm ci | |
| export TEST_URL=https://${{ env.AZURE_WEBAPP_NAME }}-staging.azurewebsites.net | |
| npm test | |
| continue-on-error: true | |
| # ======================================== | |
| # JOB 4: DEPLOY TO PRODUCTION | |
| # ======================================== | |
| deploy-prod: | |
| name: Deploy to Production | |
| runs-on: ubuntu-latest | |
| needs: deploy-staging | |
| environment: | |
| name: production | |
| url: ${{ steps.swap-slots.outputs.webapp-url }} | |
| steps: | |
| - name: 🔐 Login to Azure | |
| uses: azure/login@v1 | |
| with: | |
| creds: ${{ secrets.AZURE_CREDENTIALS }} | |
| - name: 🔄 Swap staging to production | |
| id: swap-slots | |
| run: | | |
| az webapp deployment slot swap \ | |
| --resource-group rg-az400-demo \ | |
| --name ${{ env.AZURE_WEBAPP_NAME }} \ | |
| --slot staging \ | |
| --target-slot production | |
| echo "webapp-url=https://${{ env.AZURE_WEBAPP_NAME }}.azurewebsites.net" >> $GITHUB_OUTPUT | |
| - name: 🏷️ Create release tag | |
| if: success() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const tag = `v${context.runNumber}`; | |
| await github.rest.git.createRef({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: `refs/tags/${tag}`, | |
| sha: context.sha | |
| }); | |
| console.log(`✅ Created tag: ${tag}`); | |
| # ======================================== | |
| # REUSABLE WORKFLOW: SECURITY SCAN | |
| # ======================================== | |
| security-scan: | |
| name: Security Scanning | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| - name: 🔍 Run Dependabot scan | |
| uses: github/super-linter@v5 | |
| env: | |
| DEFAULT_BRANCH: main | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VALIDATE_JAVASCRIPT_ES: true | |
| VALIDATE_JSON: true | |
| VALIDATE_YAML: true |