diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be7a0d5..9fe2ca3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,35 +61,3 @@ jobs: - uses: actions/checkout@v3 - name: Check for missing WebP versions run: ./ci/check-webp-versions.sh - - deploy: - needs: [ci, nofixups, spell-check, alt-tags-check, webp-versions-check] - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/master' && github.event_name == 'push' - permissions: - contents: read - id-token: write - env: - D2_DOCS_S3_BUCKET: s3://d2lang-docs-278852893615 - D2_DOCS_CLOUDFRONT_ID: E2NLB7I775SAF - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - uses: actions/cache@v3 - with: - path: ~/.cache/yarn/v6 - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v2 - with: - role-to-assume: arn:aws:iam::278852893615:role/d2lang-docs-deploy - aws-region: us-west-1 - - name: Install dependencies - run: yarn install --frozen-lockfile - - name: Deploy to production - run: ./ci/deploy.sh - env: - D2_DOCS_ALGOLIA_CRAWLER_API_KEY: ${{ secrets.D2_DOCS_ALGOLIA_CRAWLER_API_KEY }} diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index f6768f7..0e095de 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -12,6 +12,7 @@ concurrency: jobs: ci: + name: daily-ci runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/search-index.yml b/.github/workflows/search-index.yml new file mode 100644 index 0000000..7518193 --- /dev/null +++ b/.github/workflows/search-index.yml @@ -0,0 +1,37 @@ +name: search-index + +on: + repository_dispatch: + types: [vercel.deployment.success] + workflow_dispatch: + +permissions: {} + +concurrency: + group: production-search-index + cancel-in-progress: false + +jobs: + reindex: + if: >- + (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/master') || + (github.event_name == 'repository_dispatch' && + github.actor == 'vercel[bot]' && + github.event.client_payload.environment == 'production' && + github.event.client_payload.state.type == 'success' && + github.event.client_payload.git.ref == 'master' && + vars.D2_DOCS_VERCEL_PROJECT_ID != '' && + github.event.client_payload.project.id == vars.D2_DOCS_VERCEL_PROJECT_ID) + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - name: Reindex the live production site + env: + D2_DOCS_ALGOLIA_CRAWLER_API_KEY: ${{ secrets.D2_DOCS_ALGOLIA_CRAWLER_API_KEY }} + run: | + : "${D2_DOCS_ALGOLIA_CRAWLER_API_KEY:?Missing crawler API key}" + curl --fail --silent --show-error --connect-timeout 10 --max-time 60 \ + --header "Content-Type: application/json" \ + --request POST \ + --user "dd0bd3fe-db42-4673-89ae-e7e70dfae16b:${D2_DOCS_ALGOLIA_CRAWLER_API_KEY}" \ + "https://crawler.algolia.com/api/1/crawlers/2d841c67-ab75-4fb1-9114-f8844363d74c/reindex" diff --git a/.gitignore b/.gitignore index f730894..406db73 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Production /build +.vercel # Generated files .docusaurus @@ -22,3 +23,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +.env* diff --git a/README.md b/README.md index beb84e9..5f0136d 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![ci](https://github.com/d2lang/d2-docs/actions/workflows/ci.yml/badge.svg)](https://github.com/d2lang/d2-docs/actions/workflows/ci.yml) [![daily](https://github.com/d2lang/d2-docs/actions/workflows/daily.yml/badge.svg)](https://github.com/d2lang/d2-docs/actions/workflows/daily.yml) [![license](https://img.shields.io/github/license/d2lang/d2-docs?color=9cf)](./LICENSE) +Vercel OSS Program This is language documentation for D2, a modern, open-source text-to-diagram DSL. The source repository for that is here: @@ -18,21 +19,59 @@ A more formal reference specification is in the works. ### Development -Init submodules +Use Node.js 24 and Yarn 1.22.22. Initialize the public submodules: ```sh git submodule update --init ``` -Run dev server +Install the locked dependencies and run the development server: ```sh -yarn -yarn run dev +npx --yes --package=yarn@1.22.22 -- yarn install --frozen-lockfile +npx --yes --package=yarn@1.22.22 -- yarn run dev ``` The site is maintained in English only. +### Production build + +```sh +DOCUSAURUS_IGNORE_SSG_WARNINGS=true npx --yes --package=yarn@1.22.22 -- yarn run prod +npx --yes --package=yarn@1.22.22 -- yarn run serve +``` + +The static site is generated in `build/`. This includes the custom `404.html`, +hashed assets, and redirects from retired `/ko/` and `/zh-cn/` translations to the +English pages. Canonical URLs remain `https://d2lang.com/` with trailing slashes. + +### Hosting + +Vercel serves production at `https://d2lang.com`; `master` is the production +branch. Connect this repository to the D2 team's `d2-docs` project, select Node.js +24, and use the install/build/output settings in `vercel.json`. No build secrets +are required. Vercel initializes the public Git submodules and builds previews +for branch changes. Existing GitHub CI and daily checks continue to validate the +site independently. + +Set the GitHub repository variable `D2_DOCS_VERCEL_PROJECT_ID` to this project's +Vercel ID. Keep the existing `D2_DOCS_ALGOLIA_CRAWLER_API_KEY` GitHub secret; it is +used only by the `search-index` workflow after Vercel reports a successful +production promotion. Previews and failed builds do not trigger indexing. Run +that workflow manually on `master` after the initial DNS cutover or a manual +rollback/promotion to refresh search against the live production site. + +The configuration preserves the same-origin Plausible `/js/script.js` and +`/api/event` proxies and serves `/install.sh` from the existing +`d2lang/d2` installer on GitHub's raw content host. Hashed files under `/assets/` +have immutable browser caching; +other files use Vercel's default caching. Static filesystem routing serves the +generated pages and custom 404; no catch-all rewrite turns missing pages into 200s. + +Rollback by promoting a previous production deployment in Vercel. The former AWS +deployment job and script are retired; retained infrastructure and DNS rollback +are managed separately in `d2lang/infra`. + ### Note Diagrams are auto generated by `ci/render.sh`. diff --git a/ci/deploy.sh b/ci/deploy.sh deleted file mode 100755 index 7e20a87..0000000 --- a/ci/deploy.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -set -eu - -# Disable AWS CLI pager and auto-prompt for automated scripts -export AWS_PAGER="" - -if [ -z ${D2_DOCS_CLOUDFRONT_ID} ]; then - echo "missing env var D2_DOCS_CLOUDFRONT_ID" - exit 1 -fi - -if [ -z ${D2_DOCS_S3_BUCKET} ]; then - echo "missing env var D2_DOCS_S3_BUCKET" - exit 1 -fi - -if [ -z ${D2_DOCS_ALGOLIA_CRAWLER_API_KEY} ]; then - echo "missing env var D2_DOCS_ALGOLIA_CRAWLER_API_KEY" - exit 1 -fi - -DOCUSAURUS_IGNORE_SSG_WARNINGS=true npm run prod -aws sts get-caller-identity --no-cli-pager > /dev/null -aws s3 sync ./build ${D2_DOCS_S3_BUCKET} --delete --no-cli-pager -aws cloudfront create-invalidation --distribution-id ${D2_DOCS_CLOUDFRONT_ID} --paths "/*" --no-cli-pager - -curl -H "Content-Type: application/json" \ - -X POST \ - --user dd0bd3fe-db42-4673-89ae-e7e70dfae16b:${D2_DOCS_ALGOLIA_CRAWLER_API_KEY} \ - "https://crawler.algolia.com/api/1/crawlers/2d841c67-ab75-4fb1-9114-f8844363d74c/reindex" diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..070bc24 --- /dev/null +++ b/vercel.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "framework": null, + "installCommand": "npx --yes --package=yarn@1.22.22 -- yarn install --frozen-lockfile", + "buildCommand": "DOCUSAURUS_IGNORE_SSG_WARNINGS=true npx --yes --package=yarn@1.22.22 -- yarn run prod", + "outputDirectory": "build", + "rewrites": [ + { "source": "/install.sh", "destination": "https://raw.githubusercontent.com/d2lang/d2/master/install.sh" }, + { "source": "/js/script.js", "destination": "https://plausible.io/js/script.js" }, + { "source": "/api/event", "destination": "https://plausible.io/api/event" } + ], + "headers": [ + { + "source": "/assets/:path*", + "headers": [ + { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" } + ] + } + ] +}