fix: remove content.tabs.link and add CSP header for Cloudflare beacon #59
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 Documentation to GitHub Pages | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: "pages" | |
| cancel-in-progress: false | |
| env: | |
| BUILD_TIMESTAMP: ${{ github.run_id }}-${{ github.run_number }} | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| clean: true | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('apps/docs-site/requirements.txt') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install MkDocs and dependencies | |
| run: | | |
| pip install --upgrade pip | |
| pip install -r apps/docs-site/requirements.txt | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Test docs validator tooling | |
| run: cargo test -q --manifest-path src/tools/docs-validator-rs/Cargo.toml | |
| - name: Inject AI configuration from secrets | |
| env: | |
| AI_API_BASE_URL: ${{ secrets.AI_API_BASE_URL }} | |
| AI_API_TOKEN: ${{ secrets.AI_API_TOKEN }} | |
| AI_MODEL_NAME: ${{ secrets.AI_MODEL_NAME }} | |
| OPEN_NOTEBOOK_ENABLED: ${{ secrets.OPEN_NOTEBOOK_ENABLED }} | |
| OPEN_NOTEBOOK_URL: ${{ secrets.OPEN_NOTEBOOK_URL }} | |
| OPEN_NOTEBOOK_TOKEN: ${{ secrets.OPEN_NOTEBOOK_TOKEN }} | |
| run: | | |
| CONFIG_FILE="content/docs/javascripts/ai-config.js" | |
| if [ -n "$AI_API_BASE_URL" ]; then | |
| if [[ "$AI_API_BASE_URL" != https://* ]]; then | |
| echo "::error::AI_API_BASE_URL must be an absolute https:// URL. Got: '${AI_API_BASE_URL}'" | |
| exit 1 | |
| fi | |
| if [[ "$AI_API_BASE_URL" != */v[0-9]* ]]; then | |
| echo "::warning::AI_API_BASE_URL does not contain a version segment (e.g. /v1). Got: '${AI_API_BASE_URL}'. The JS client appends /chat/completions directly — ensure the backend routes unversioned paths, or add /v1 to the secret." | |
| fi | |
| if [[ "$AI_API_BASE_URL" == */ ]]; then | |
| echo "::warning::AI_API_BASE_URL ends with a trailing slash. Got: '${AI_API_BASE_URL}'. The JS client strips it at runtime — please fix the secret to remove the trailing slash." | |
| fi | |
| fi | |
| if [ -f "$CONFIG_FILE" ]; then | |
| if [ -n "$AI_API_BASE_URL" ]; then | |
| sed -i "s|%%AI_API_BASE_URL%%|${AI_API_BASE_URL}|g" "$CONFIG_FILE" | |
| fi | |
| if [ -n "$AI_API_TOKEN" ]; then | |
| sed -i "s|%%AI_API_TOKEN%%|${AI_API_TOKEN}|g" "$CONFIG_FILE" | |
| fi | |
| if [ -n "$AI_MODEL_NAME" ]; then | |
| sed -i "s|%%AI_MODEL_NAME%%|${AI_MODEL_NAME}|g" "$CONFIG_FILE" | |
| fi | |
| if [ -n "$OPEN_NOTEBOOK_ENABLED" ]; then | |
| sed -i "s|%%OPEN_NOTEBOOK_ENABLED%%|${OPEN_NOTEBOOK_ENABLED}|g" "$CONFIG_FILE" | |
| fi | |
| if [ -n "$OPEN_NOTEBOOK_URL" ]; then | |
| sed -i "s|%%OPEN_NOTEBOOK_URL%%|${OPEN_NOTEBOOK_URL}|g" "$CONFIG_FILE" | |
| fi | |
| if [ -n "$OPEN_NOTEBOOK_TOKEN" ]; then | |
| sed -i "s|%%OPEN_NOTEBOOK_TOKEN%%|${OPEN_NOTEBOOK_TOKEN}|g" "$CONFIG_FILE" | |
| fi | |
| echo "AI configuration injected successfully" | |
| else | |
| echo "Warning: AI config file not found at $CONFIG_FILE" | |
| fi | |
| - name: Clean previous build artifacts | |
| run: | | |
| rm -rf dist/site/ | |
| rm -rf .cache/ | |
| - name: Build MkDocs site (clean build) | |
| working-directory: apps/docs-site | |
| run: | | |
| mkdocs build --clean | |
| echo "Build completed at $(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| - name: Add build metadata | |
| run: | | |
| BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) | |
| cat > dist/site/build-info.json << EOF | |
| { | |
| "buildTime": "$BUILD_TIME", | |
| "buildId": "${{ github.run_id }}", | |
| "buildNumber": "${{ github.run_number }}", | |
| "commit": "${{ github.sha }}", | |
| "ref": "${{ github.ref }}" | |
| } | |
| EOF | |
| - name: Copy extra static content to site (post-build) | |
| run: | | |
| bash src/automation/site/sync-extra-assets.sh dist/site/extra | |
| - name: Create CNAME file | |
| run: echo 'docs.nodove.com' > dist/site/CNAME | |
| - name: Create cache headers configuration | |
| run: | | |
| cat > dist/site/_headers << 'EOF' | |
| /assets/* | |
| Cache-Control: public, max-age=31536000, immutable | |
| /stylesheets/* | |
| Cache-Control: public, max-age=0, must-revalidate | |
| /javascripts/* | |
| Cache-Control: public, max-age=0, must-revalidate | |
| /* | |
| Content-Security-Policy: script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; | |
| /*.html | |
| Cache-Control: public, max-age=0, must-revalidate | |
| /*/index.html | |
| Cache-Control: public, max-age=0, must-revalidate | |
| /build-info.json | |
| Cache-Control: no-store | |
| EOF | |
| - name: Verify build output | |
| run: | | |
| echo "Build output statistics:" | |
| echo " Total files: $(find dist/site -type f | wc -l)" | |
| echo " Total size: $(du -sh dist/site | cut -f1)" | |
| echo " CSS files: $(find dist/site -name '*.css' | wc -l)" | |
| echo " JS files: $(find dist/site -name '*.js' | wc -l)" | |
| echo " HTML files: $(find dist/site -name '*.html' | wc -l)" | |
| if [ -f "dist/site/stylesheets/extra.css" ]; then | |
| echo "extra.css exists ($(wc -l < dist/site/stylesheets/extra.css) lines)" | |
| else | |
| echo "WARNING: extra.css not found!" | |
| fi | |
| if [ -f "dist/site/javascripts/ai-chatbot.js" ]; then | |
| echo "ai-chatbot.js exists" | |
| else | |
| echo "WARNING: ai-chatbot.js not found!" | |
| fi | |
| - name: Setup Pages | |
| uses: actions/configure-pages@v4 | |
| - name: Upload artifact | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: ./dist/site | |
| deploy: | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| runs-on: ubuntu-latest | |
| needs: build | |
| if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' | |
| steps: | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 | |
| - name: Deployment Summary | |
| run: | | |
| echo "Deployment completed successfully!" | |
| echo " URL: ${{ steps.deployment.outputs.page_url }}" | |
| echo " Commit: ${{ github.sha }}" | |
| echo " Time: $(date -u +%Y-%m-%dT%H:%M:%SZ)" |