diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index f3d9ca0f37..87900f1187 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -1,206 +1,202 @@ - name: Build and deploy Docusaurus site to Azure Blob Storage - - on: - push: - branches: - - main - - dev - workflow_dispatch: - inputs: - environment: - description: 'Environment to deploy to' - required: true - default: 'development' - type: choice - options: - - development - - production - - jobs: - determine-environment: - runs-on: ubuntu-latest - outputs: - environment: ${{ steps.set-env.outputs.environment }} - steps: - - name: Determine environment - id: set-env - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT - elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then - echo "environment=production" >> $GITHUB_OUTPUT - else - echo "environment=development" >> $GITHUB_OUTPUT - fi - - build: - runs-on: self-hosted - needs: determine-environment - environment: ${{ needs.determine-environment.outputs.environment }} - permissions: - contents: read - - steps: - - name: Check out source code - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '22.x' - - - name: Cache Node.js dependencies - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Cache Docusaurus build - uses: actions/cache@v3 - id: cache-build - with: - path: | - .docusaurus - key: ${{ runner.os }}-docusaurus-${{ hashFiles('src/**', 'docs/**', 'blog/**', 'docusaurus.config.js', 'sidebars.js') }} - restore-keys: | - ${{ runner.os }}-docusaurus- - - - name: Cache webpack - uses: actions/cache@v3 - with: - path: node_modules/.cache - key: ${{ runner.os }}-webpack-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-webpack- - - - name: Install dependencies and build site - run: | - npm ci - - # Check if we have a valid cached build - if [[ "${{ steps.cache-build.outputs.cache-hit }}" == "true" ]]; then - echo "Build cache found, checking if rebuild needed..." - # Docusaurus will intelligently rebuild only what's changed - else - echo "No build cache found, performing full build..." - fi - - # Run build - Docusaurus will use its internal caching - npm run build - env: - NODE_OPTIONS: "--max-old-space-size=16384" - DOCUSAURUS_URL: "https://${{ secrets.STORAGE_ACCOUNT_NAME }}.z13.web.core.windows.net" - # Add any other environment-specific build variables here - NODE_ENV: ${{ needs.determine-environment.outputs.environment }} - - - name: Upload artifact for deployment - uses: actions/upload-artifact@v4 - with: - name: build-output - path: build/ - - deploy: - runs-on: ubuntu-latest - needs: [build, determine-environment] - environment: ${{ needs.determine-environment.outputs.environment }} - - steps: - - name: Download build artifact - uses: actions/download-artifact@v4 - with: - name: build-output - path: build/ - - - name: Install azcopy - run: | - # Download and install azcopy for faster uploads - wget -O azcopy.tar.gz https://aka.ms/downloadazcopy-v10-linux - tar -xf azcopy.tar.gz --strip-components=1 - sudo mv azcopy /usr/local/bin/ - azcopy --version - - - name: Upload to Azure Blob Storage with AzCopy and comprehensive MIME types - run: | - echo "Deploying to ${{ needs.determine-environment.outputs.environment }} environment" - echo "Starting high-performance sync of changed files with proper MIME types..." - - # Create SAS token for azcopy (more secure than using key directly) - end_date=$(date -u -d "30 minutes" '+%Y-%m-%dT%H:%MZ') - sas_token=$(az storage container generate-sas \ - --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} \ - --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} \ - --name '$web' \ - --permissions dlrw \ - --expiry $end_date \ - --output tsv) - - # Use azcopy sync without content type mapping (will be set in fallback step) - azcopy sync "./build/" \ - "https://${{ secrets.STORAGE_ACCOUNT_NAME }}.blob.core.windows.net/\$web?$sas_token" \ - --delete-destination=true \ - --compare-hash=MD5 \ - --log-level=INFO \ - --cap-mbps=0 \ - --block-size-mb=4 - - echo "Sync completed with comprehensive MIME types!" - - - name: Set MIME types for all file types - run: | - echo "Setting MIME types for all file types..." - - # Install Azure CLI if not available - if ! command -v az &> /dev/null; then - curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash - fi - - # Web files - echo "Setting MIME types for web files..." - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.css" --content-type "text/css" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.js" --content-type "application/javascript" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.mjs" --content-type "application/javascript" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.json" --content-type "application/json" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.html" --content-type "text/html" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.htm" --content-type "text/html" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.xml" --content-type "application/xml" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.txt" --content-type "text/plain" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - - # Images - echo "Setting MIME types for images..." - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.png" --content-type "image/png" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.jpg" --content-type "image/jpeg" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.jpeg" --content-type "image/jpeg" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.gif" --content-type "image/gif" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.webp" --content-type "image/webp" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.svg" --content-type "image/svg+xml" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.ico" --content-type "image/x-icon" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - - # Fonts - echo "Setting MIME types for fonts..." - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.woff" --content-type "font/woff" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.woff2" --content-type "font/woff2" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.ttf" --content-type "font/ttf" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.otf" --content-type "font/otf" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true - - echo "All MIME types set successfully!" - - - name: Purge CDN endpoint (if configured) - run: | - if [[ -n "${{ secrets.CDN_ENDPOINT_NAME }}" ]] && [[ -n "${{ secrets.CDN_PROFILE_NAME }}" ]] && [[ -n "${{ secrets.CDN_RESOURCE_GROUP }}" ]]; then - echo "Note: CDN purge requires Azure login. Skipping CDN purge when using storage key authentication." - echo "To use CDN purge, you'll need to use Azure AD authentication or purge CDN manually." - else - echo "CDN configuration not found, skipping CDN purge." - fi - - - name: Display deployment URL - run: | - echo "🚀 Deployment complete!" - echo "Environment: ${{ needs.determine-environment.outputs.environment }}" - echo "URL: https://${{ secrets.STORAGE_ACCOUNT_NAME }}.z13.web.core.windows.net" - if [[ -n "${{ secrets.CUSTOM_DOMAIN }}" ]]; then - echo "Custom Domain: ${{ secrets.CUSTOM_DOMAIN }}" - fi - echo "All files deployed with proper MIME types for optimal browser compatibility!" \ No newline at end of file +name: Build and deploy Docusaurus site to Azure Blob Storage + +on: + push: + branches: + - main + - dev + workflow_dispatch: + inputs: + environment: + description: 'Environment to deploy to' + required: true + default: 'development' + type: choice + options: + - development + - production + +jobs: + determine-environment: + runs-on: ubuntu-latest + outputs: + environment: ${{ steps.set-env.outputs.environment }} + steps: + - name: Determine environment + id: set-env + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT + elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then + echo "environment=production" >> $GITHUB_OUTPUT + else + echo "environment=development" >> $GITHUB_OUTPUT + fi + + build: + runs-on: self-hosted + needs: determine-environment + environment: ${{ needs.determine-environment.outputs.environment }} + permissions: + contents: read + env: + APP_EXTERNAL_URL: ${{ secrets.APP_EXTERNAL_URL || vars.APP_EXTERNAL_URL }} + steps: + - name: Check out source code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '22.x' + + - name: Cache Node.js dependencies + uses: actions/cache@v3 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Cache Docusaurus build + uses: actions/cache@v3 + id: cache-build + with: + path: | + .docusaurus + key: ${{ runner.os }}-docusaurus-${{ hashFiles('src/**', 'docs/**', 'blog/**', 'docusaurus.config.js', 'sidebars.js') }} + restore-keys: | + ${{ runner.os }}-docusaurus- + + - name: Cache webpack + uses: actions/cache@v3 + with: + path: node_modules/.cache + key: ${{ runner.os }}-webpack-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-webpack- + + - name: Install dependencies and build site + run: | + npm ci + + if [[ "${{ steps.cache-build.outputs.cache-hit }}" == "true" ]]; then + echo "Build cache found, checking if rebuild needed..." + else + echo "No build cache found, performing full build..." + fi + + npm run build + env: + NODE_OPTIONS: "--max-old-space-size=16384" + NODE_ENV: ${{ needs.determine-environment.outputs.environment }} + + - name: Upload artifact for deployment + uses: actions/upload-artifact@v4 + with: + name: build-output + path: build/ + + deploy: + runs-on: ubuntu-latest + needs: [build, determine-environment] + environment: ${{ needs.determine-environment.outputs.environment }} + + steps: + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: build-output + path: build/ + + - name: Install azcopy + run: | + wget -O azcopy.tar.gz https://aka.ms/downloadazcopy-v10-linux + tar -xf azcopy.tar.gz --strip-components=1 + sudo mv azcopy /usr/local/bin/ + azcopy --version + + - name: Install Azure CLI + run: | + if ! command -v az &> /dev/null; then + curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash + fi + az version + + - name: Upload to Azure Blob Storage with AzCopy and comprehensive MIME types + run: | + echo "Deploying to ${{ needs.determine-environment.outputs.environment }} environment" + echo "Starting high-performance sync of changed files with proper MIME types..." + + # Create SAS token for azcopy (using account key) + end_date=$(date -u -d "30 minutes" '+%Y-%m-%dT%H:%MZ') + sas_token=$(az storage container generate-sas \ + --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} \ + --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} \ + --name '$web' \ + --permissions dlrw \ + --expiry $end_date \ + --output tsv) + + azcopy sync "./build/" \ + "https://${{ secrets.STORAGE_ACCOUNT_NAME }}.blob.core.windows.net/\$web?$sas_token" \ + --delete-destination=true \ + --compare-hash=MD5 \ + --log-level=INFO \ + --cap-mbps=0 \ + --block-size-mb=4 + + echo "Sync completed!" + + - name: Set MIME types for all file types + run: | + echo "Setting MIME types for all file types..." + + # Web files + echo "Setting MIME types for web files..." + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.css" --content-type "text/css" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.js" --content-type "application/javascript" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.mjs" --content-type "application/javascript" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.json" --content-type "application/json" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.html" --content-type "text/html" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.htm" --content-type "text/html" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.xml" --content-type "application/xml" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.txt" --content-type "text/plain" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + + # Images + echo "Setting MIME types for images..." + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.png" --content-type "image/png" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.jpg" --content-type "image/jpeg" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.jpeg" --content-type "image/jpeg" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.gif" --content-type "image/gif" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.webp" --content-type "image/webp" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.svg" --content-type "image/svg+xml" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.ico" --content-type "image/x-icon" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + + # Fonts + echo "Setting MIME types for fonts..." + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.woff" --content-type "font/woff" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.woff2" --content-type "font/woff2" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.ttf" --content-type "font/ttf" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + az storage blob update-batch --account-name ${{ secrets.STORAGE_ACCOUNT_NAME }} --account-key ${{ secrets.STORAGE_ACCOUNT_KEY }} --source '$web' --pattern "*.otf" --content-type "font/otf" --if-unmodified-since "1970-01-01T00:00:00Z" --no-progress || true + + echo "All MIME types set successfully!" + + - name: Purge CDN endpoint (if configured) + run: | + if [[ -n "${{ secrets.CDN_ENDPOINT_NAME }}" ]] && [[ -n "${{ secrets.CDN_PROFILE_NAME }}" ]] && [[ -n "${{ secrets.CDN_RESOURCE_GROUP }}" ]]; then + echo "Note: CDN purge requires Azure login. Skipping CDN purge when using storage key authentication." + echo "To use CDN purge, you'll need to use Azure AD authentication or purge CDN manually." + else + echo "CDN configuration not found, skipping CDN purge." + fi + + - name: Display deployment URL + run: | + echo "🚀 Deployment complete!" + echo "Environment: ${{ needs.determine-environment.outputs.environment }}" + echo "URL: https://${{ secrets.STORAGE_ACCOUNT_NAME }}.z13.web.core.windows.net" + if [[ -n "${{ secrets.CUSTOM_DOMAIN }}" ]]; then + echo "Custom Domain: ${{ secrets.CUSTOM_DOMAIN }}" + fi + echo "All files deployed with proper MIME types for optimal browser compatibility!"