build(deps-dev): bump @types/node from 26.4.0 to 26.4.1 in /src/micro… #1052
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, Test, and Deploy Try .NET API | |
| on: | |
| push: | |
| branches: ["main"] | |
| pull_request: | |
| branches: ["main"] | |
| workflow_dispatch: | |
| permissions: | |
| id-token: write | |
| contents: read | |
| jobs: | |
| build-and-test: | |
| runs-on: ubuntu-latest | |
| environment: "BuildAndUploadImage" | |
| permissions: | |
| actions: write # required for docker/build-push-action GHA cache writes | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Node.js environment | |
| uses: ./.github/actions/setup-node | |
| - name: Set up .NET environment | |
| uses: ./.github/actions/setup-dotnet | |
| - name: Run ciTest for microsoft-trydotnet | |
| working-directory: src/microsoft-trydotnet | |
| run: npm run ciTest | |
| - name: Run ciTest for microsoft-trydotnet-editor | |
| working-directory: src/microsoft-trydotnet-editor | |
| run: npm run ciTest | |
| - name: Run .NET Tests | |
| id: run-dotnet-tests | |
| run: dotnet test --no-build --configuration Release --blame-hang-timeout 15m --blame-hang-dump-type full -l trx --results-directory ./TestResults | |
| env: | |
| POCKETLOGGER_LOG_PATH: ${{ github.workspace }}/artifacts/logs/pocketlogger.log | |
| - name: Convert TRX to Playlist | |
| if: ${{ steps.run-dotnet-tests.outcome == 'failure' || failure() }} | |
| uses: BenjaminMichaelis/trx-to-vsplaylist@v4 | |
| with: | |
| trx-file-path: './TestResults/*.trx' | |
| test-outcomes: 'Failed' | |
| artifact-name: 'linux-test-playlists' | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| id: setup-buildx | |
| - name: Cache Docker build mounts (main) | |
| if: github.ref == 'refs/heads/main' | |
| uses: actions/cache@v6 | |
| id: cache-mounts-main | |
| with: | |
| path: .buildkit-cache | |
| key: buildkit-cache-${{ hashFiles('Dockerfile', 'Directory.Packages.props', 'NuGet.config', 'src/**/package-lock.json') }} | |
| restore-keys: | | |
| buildkit-cache- | |
| - name: Restore Docker build mounts (PR) | |
| if: github.event_name == 'pull_request' || github.event_name == 'merge_group' | |
| uses: actions/cache/restore@v6 | |
| id: cache-mounts-pr | |
| with: | |
| path: .buildkit-cache | |
| key: buildkit-cache-${{ hashFiles('Dockerfile', 'Directory.Packages.props', 'NuGet.config', 'src/**/package-lock.json') }} | |
| restore-keys: | | |
| buildkit-cache- | |
| - name: Inject Docker cache mounts | |
| uses: reproducible-containers/buildkit-cache-dance@v3 | |
| with: | |
| builder: ${{ steps.setup-buildx.outputs.name }} | |
| cache-dir: .buildkit-cache | |
| dockerfile: Dockerfile | |
| skip-extraction: ${{ github.ref != 'refs/heads/main' || steps.cache-mounts-main.outputs.cache-hit == 'true' }} | |
| # Build but no push with a PR | |
| - name: Docker build (no push) | |
| if: github.event_name == 'pull_request' || github.event_name == 'merge_group' | |
| uses: docker/build-push-action@v7 | |
| with: | |
| push: false | |
| tags: temp-pr-validation | |
| file: ./Dockerfile | |
| cache-from: type=gha,scope=try-main | |
| # Only build for dev registry — prod gets the image via az acr import in deploy-production | |
| - name: Build Container Image | |
| if: github.ref == 'refs/heads/main' | |
| uses: docker/build-push-action@v7 | |
| with: | |
| tags: ${{ vars.DEVCONTAINER_REGISTRY }}/try:${{ github.sha }},${{ vars.DEVCONTAINER_REGISTRY }}/try:latest | |
| file: ./Dockerfile | |
| context: . | |
| outputs: type=docker,dest=${{ github.workspace }}/tryimage.tar | |
| cache-from: type=gha,scope=try-main | |
| cache-to: type=gha,mode=max,scope=try-main | |
| - name: Upload artifact | |
| if: github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@v7.0.1 | |
| with: | |
| name: tryimage | |
| path: ${{ github.workspace }}/tryimage.tar | |
| build-and-test-windows: | |
| # Ensures .NET build and unit tests pass on Windows, matching the original | |
| # Azure DevOps Windows_NT job. Integration tests are covered separately. | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Node.js environment | |
| uses: ./.github/actions/setup-node | |
| - name: Set up .NET environment | |
| uses: ./.github/actions/setup-dotnet | |
| - name: Run .NET Tests | |
| id: run-dotnet-tests | |
| run: dotnet test --no-build --configuration Release --blame-hang-timeout 15m --blame-hang-dump-type full -l trx --results-directory ./TestResults | |
| env: | |
| POCKETLOGGER_LOG_PATH: ${{ github.workspace }}/artifacts/logs/pocketlogger.log | |
| - name: Convert TRX to Playlist | |
| if: ${{ steps.run-dotnet-tests.outcome == 'failure' || failure() }} | |
| uses: BenjaminMichaelis/trx-to-vsplaylist@v4 | |
| with: | |
| trx-file-path: './TestResults/*.trx' | |
| test-outcomes: 'Failed' | |
| artifact-name: 'windows-test-playlists' | |
| integration-tests: | |
| # Integration tests use Playwright and are gated behind RunIntegrationTests=true. | |
| # IntegrationTestFactAttribute explicitly skips these tests on Linux, so a | |
| # Windows runner is required to actually execute them. | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Node.js environment | |
| uses: ./.github/actions/setup-node | |
| - name: Set up .NET environment | |
| uses: ./.github/actions/setup-dotnet | |
| - name: Run .NET Integration Tests | |
| id: run-dotnet-integration-tests | |
| run: dotnet test --no-build --configuration Release --blame-hang-timeout 15m --blame-hang-dump-type full -l trx --results-directory ./TestResults | |
| env: | |
| RunIntegrationTests: true | |
| POCKETLOGGER_LOG_PATH: ${{ github.workspace }}/artifacts/logs/pocketlogger.log | |
| TRYDOTNET_PREBUILDS_PATH: ${{ github.workspace }}/artifacts/trydotnet-prebuilds | |
| - name: Convert TRX to Playlist | |
| if: ${{ steps.run-dotnet-integration-tests.outcome == 'failure' || failure() }} | |
| uses: BenjaminMichaelis/trx-to-vsplaylist@v4 | |
| with: | |
| trx-file-path: './TestResults/*.trx' | |
| test-outcomes: 'Failed' | |
| artifact-name: 'integration-test-playlists' | |
| deploy-development: | |
| if: github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| needs: [build-and-test, build-and-test-windows, integration-tests] | |
| concurrency: | |
| group: deploy-development-try | |
| cancel-in-progress: false | |
| environment: | |
| name: "Development" | |
| permissions: | |
| id-token: write | |
| contents: read | |
| steps: | |
| - name: Azure Login | |
| uses: azure/login@v3 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: Download artifact | |
| uses: actions/download-artifact@v8.0.1 | |
| with: | |
| name: tryimage | |
| path: ${{ github.workspace }} | |
| - name: Load image | |
| run: | | |
| docker load --input ${{ github.workspace }}/tryimage.tar | |
| docker image ls -a | |
| - name: Log in to container registry | |
| run: | | |
| REGISTRY="${{ vars.DEVCONTAINER_REGISTRY }}" | |
| az acr login --name "${REGISTRY%.azurecr.io}" | |
| - name: Push Image to Dev Container Registry | |
| run: docker push --all-tags ${{ vars.DEVCONTAINER_REGISTRY }}/try | |
| - name: Deploy to Container App | |
| env: | |
| CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }} | |
| RESOURCEGROUP: ${{ vars.RESOURCEGROUP }} | |
| run: | | |
| az extension add --name containerapp --upgrade --only-show-errors | |
| az containerapp update \ | |
| --name "$CONTAINER_APP_NAME" \ | |
| --resource-group "$RESOURCEGROUP" \ | |
| --image "${{ vars.DEVCONTAINER_REGISTRY }}/try:${{ github.sha }}" | |
| deploy-production: | |
| if: github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| needs: deploy-development | |
| concurrency: | |
| group: deploy-production-try | |
| cancel-in-progress: false | |
| environment: | |
| name: "Production" | |
| permissions: | |
| id-token: write | |
| contents: write # needed for git deploy tag | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Azure Login | |
| uses: azure/login@v3 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| # Server-side copy from dev ACR to prod ACR — no artifact download needed. | |
| # PREREQUISITE: prod OIDC identity must have AcrPull on the dev ACR (Terraform RBAC). | |
| - name: Import image from dev ACR to prod ACR | |
| id: import | |
| run: | | |
| DEV_ACR="${{ vars.DEVCONTAINER_REGISTRY }}" | |
| PROD_ACR="${{ vars.PRODCONTAINER_REGISTRY }}" | |
| az acr import \ | |
| --name "${PROD_ACR%.azurecr.io}" \ | |
| --source "${DEV_ACR}/try:${{ github.sha }}" \ | |
| --image "try:${{ github.sha }}" \ | |
| --image "try:latest" \ | |
| --force | |
| DIGEST=$(az acr repository show \ | |
| --name "${PROD_ACR%.azurecr.io}" \ | |
| --image "try:${{ github.sha }}" \ | |
| --query "digest" -o tsv) | |
| if [ -z "$DIGEST" ]; then | |
| echo "::error::Failed to capture image digest from prod ACR after import" | |
| exit 1 | |
| fi | |
| echo "digest=$DIGEST" >> $GITHUB_OUTPUT | |
| - name: Deploy to Container App | |
| env: | |
| CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }} | |
| RESOURCEGROUP: ${{ vars.RESOURCEGROUP }} | |
| run: | | |
| az extension add --name containerapp --upgrade --only-show-errors | |
| az containerapp update \ | |
| --name "$CONTAINER_APP_NAME" \ | |
| --resource-group "$RESOURCEGROUP" \ | |
| --image "${{ vars.PRODCONTAINER_REGISTRY }}/try@${{ steps.import.outputs.digest }}" | |
| - name: Verify deployed image | |
| env: | |
| CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }} | |
| RESOURCEGROUP: ${{ vars.RESOURCEGROUP }} | |
| run: | | |
| DEPLOYED=$(az containerapp show \ | |
| --name "$CONTAINER_APP_NAME" \ | |
| --resource-group "$RESOURCEGROUP" \ | |
| --query "properties.template.containers[0].image" -o tsv) | |
| EXPECTED="${{ vars.PRODCONTAINER_REGISTRY }}/try@${{ steps.import.outputs.digest }}" | |
| if [ "$DEPLOYED" != "$EXPECTED" ]; then | |
| echo "::error::Image mismatch! Expected $EXPECTED but found $DEPLOYED" | |
| exit 1 | |
| fi | |
| echo "Deployed image verified: $DEPLOYED" | |
| - name: Smoke test | |
| env: | |
| CONTAINER_APP_NAME: ${{ vars.CONTAINER_APP_NAME }} | |
| RESOURCEGROUP: ${{ vars.RESOURCEGROUP }} | |
| run: | | |
| FQDN=$(az containerapp show \ | |
| --name "$CONTAINER_APP_NAME" \ | |
| --resource-group "$RESOURCEGROUP" \ | |
| --query "properties.configuration.ingress.fqdn" -o tsv) | |
| # --retry-all-errors ensures HTTP 5xx (cold-start 503s) also trigger retries | |
| curl --fail --retry 10 --retry-delay 15 --retry-all-errors --max-time 30 "https://$FQDN/" | |
| - name: Tag commit as deployed | |
| run: | | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git config user.name "github-actions[bot]" | |
| # -f allows re-tagging the same SHA on workflow re-runs | |
| git tag -f "deployed/prod/${{ github.sha }}" | |
| git push origin "deployed/prod/${{ github.sha }}" --force | |
| - name: Logout of Azure CLI | |
| if: always() | |
| uses: azure/CLI@v3 | |
| with: | |
| inlineScript: | | |
| az logout | |
| az cache purge | |
| az account clear |