generate deploy docs

Ben Kunkle created

Change summary

.github/workflows/deploy_docs.yml                |  85 +++++++++++
.github/workflows/run_tests.yml                  |  22 +-
tooling/xtask/src/tasks/workflows.rs             |   2 
tooling/xtask/src/tasks/workflows/deploy_docs.rs | 133 ++++++++++++++++++
tooling/xtask/src/tasks/workflows/run_tests.rs   |  51 ------
tooling/xtask/src/tasks/workflows/vars.rs        |   3 
6 files changed, 237 insertions(+), 59 deletions(-)

Detailed changes

.github/workflows/deploy_docs.yml 🔗

@@ -0,0 +1,85 @@
+# Generated from xtask::workflows::deploy_docs
+# Rebuild with `cargo xtask workflows`.
+name: deploy_docs
+on:
+  push:
+    branches:
+    - main
+    - staged-docs-releases
+jobs:
+  deploy_docs_job:
+    if: github.repository_owner == 'zed-industries'
+    name: Build and Deploy Docs
+    runs-on: namespace-profile-16x32-ubuntu-2204
+    env:
+      DOCS_AMPLITUDE_API_KEY: ${{ secrets.DOCS_AMPLITUDE_API_KEY }}
+    steps:
+    - name: steps::checkout_repo
+      uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+      with:
+        clean: false
+    - name: steps::setup_cargo_config
+      run: |
+        mkdir -p ./../.cargo
+        cp ./.cargo/ci-config.toml ./../.cargo/config.toml
+    - name: steps::cache_rust_dependencies_namespace
+      uses: namespacelabs/nscloud-cache-action@v1
+      with:
+        cache: rust
+        path: ~/.rustup
+    - name: steps::setup_linux
+      run: ./script/linux
+    - name: steps::install_mold
+      run: ./script/install-mold
+    - name: steps::download_wasi_sdk
+      run: ./script/download-wasi-sdk
+    - name: ./script/generate-action-metadata
+      run: ./script/generate-action-metadata
+    - name: deploy_docs::lychee_link_check
+      uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332
+      with:
+        args: --no-progress --exclude '^http' './docs/src/**/*'
+        fail: true
+        jobSummary: false
+    - name: deploy_docs::install_mdbook
+      uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08
+      with:
+        mdbook-version: 0.4.37
+    - name: deploy_docs::build_docs_book
+      run: |
+        mkdir -p target/deploy
+        mdbook build ./docs --dest-dir=../target/deploy/docs/
+    - name: deploy_docs::lychee_link_check
+      uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332
+      with:
+        args: --no-progress --exclude '^http' 'target/deploy/docs'
+        fail: true
+        jobSummary: false
+    - name: deploy_docs::deploy_docs_to_pages
+      uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65
+      with:
+        apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+        accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+        command: pages deploy target/deploy --project-name=docs
+    - name: deploy_docs::deploy_install_script
+      uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65
+      with:
+        apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+        accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+        command: r2 object put -f script/install.sh zed-open-source-website-assets/install.sh
+    - name: deploy_docs::deploy_docs_worker
+      uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65
+      with:
+        apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+        accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+        command: deploy .cloudflare/docs-proxy/src/worker.js
+    - name: deploy_docs::upload_wrangler_logs
+      if: always()
+      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+      with:
+        name: wrangler_logs
+        path: /home/runner/.config/.wrangler/logs/
+    timeout-minutes: 60
+defaults:
+  run:
+    shell: bash -euxo pipefail {0}

.github/workflows/run_tests.yml 🔗

@@ -502,7 +502,9 @@ jobs:
     needs:
     - orchestrate
     if: needs.orchestrate.outputs.run_docs == 'true'
-    runs-on: namespace-profile-8x16-ubuntu-2204
+    runs-on: namespace-profile-16x32-ubuntu-2204
+    env:
+      DOCS_AMPLITUDE_API_KEY: ${{ secrets.DOCS_AMPLITUDE_API_KEY }}
     steps:
     - name: steps::checkout_repo
       uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
@@ -517,12 +519,6 @@ jobs:
       with:
         cache: rust
         path: ~/.rustup
-    - name: run_tests::check_docs::lychee_link_check
-      uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332
-      with:
-        args: --no-progress --exclude '^http' './docs/src/**/*'
-        fail: true
-        jobSummary: false
     - name: steps::setup_linux
       run: ./script/linux
     - name: steps::install_mold
@@ -531,15 +527,21 @@ jobs:
       run: ./script/download-wasi-sdk
     - name: ./script/generate-action-metadata
       run: ./script/generate-action-metadata
-    - name: run_tests::check_docs::install_mdbook
+    - name: deploy_docs::lychee_link_check
+      uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332
+      with:
+        args: --no-progress --exclude '^http' './docs/src/**/*'
+        fail: true
+        jobSummary: false
+    - name: deploy_docs::install_mdbook
       uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08
       with:
         mdbook-version: 0.4.37
-    - name: run_tests::check_docs::build_docs
+    - name: deploy_docs::build_docs_book
       run: |
         mkdir -p target/deploy
         mdbook build ./docs --dest-dir=../target/deploy/docs/
-    - name: run_tests::check_docs::lychee_link_check
+    - name: deploy_docs::lychee_link_check
       uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332
       with:
         args: --no-progress --exclude '^http' 'target/deploy/docs'

tooling/xtask/src/tasks/workflows.rs 🔗

@@ -11,6 +11,7 @@ mod cherry_pick;
 mod compare_perf;
 mod danger;
 mod deploy_collab;
+mod deploy_docs;
 mod extension_bump;
 mod extension_tests;
 mod extension_workflow_rollout;
@@ -135,6 +136,7 @@ pub fn run_workflows(_: GenerateWorkflowArgs) -> Result<()> {
         WorkflowFile::zed(compare_perf::compare_perf),
         WorkflowFile::zed(danger::danger),
         WorkflowFile::zed(deploy_collab::deploy_collab),
+        WorkflowFile::zed(deploy_docs::deploy_docs),
         WorkflowFile::zed(extension_bump::extension_bump),
         WorkflowFile::zed(extension_tests::extension_tests),
         WorkflowFile::zed(extension_workflow_rollout::extension_workflow_rollout),

tooling/xtask/src/tasks/workflows/deploy_docs.rs 🔗

@@ -0,0 +1,133 @@
+use gh_workflow::{Event, Expression, Job, Push, Run, Step, Use, Workflow};
+
+use crate::tasks::workflows::{
+    runners::{self, Platform},
+    steps::{self, FluentBuilder as _, NamedJob, named, release_job},
+    vars,
+};
+
+pub(crate) fn lychee_link_check(dir: &str) -> Step<Use> {
+    named::uses(
+        "lycheeverse",
+        "lychee-action",
+        "82202e5e9c2f4ef1a55a3d02563e1cb6041e5332",
+    ) // v2.4.1
+    .add_with(("args", format!("--no-progress --exclude '^http' '{dir}'")))
+    .add_with(("fail", true))
+    .add_with(("jobSummary", false))
+}
+
+pub(crate) fn install_mdbook() -> Step<Use> {
+    named::uses(
+        "peaceiris",
+        "actions-mdbook",
+        "ee69d230fe19748b7abf22df32acaa93833fad08", // v2
+    )
+    .with(("mdbook-version", "0.4.37"))
+}
+
+pub(crate) fn build_docs_book() -> Step<Run> {
+    named::bash(indoc::indoc! {r#"
+        mkdir -p target/deploy
+        mdbook build ./docs --dest-dir=../target/deploy/docs/
+    "#})
+}
+
+fn deploy_docs_to_pages() -> Step<Use> {
+    named::uses(
+        "cloudflare",
+        "wrangler-action",
+        "da0e0dfe58b7a431659754fdf3f186c529afbe65",
+    ) // v3
+    .add_with(("apiToken", vars::CLOUDFLARE_API_TOKEN))
+    .add_with(("accountId", vars::CLOUDFLARE_ACCOUNT_ID))
+    .add_with(("command", "pages deploy target/deploy --project-name=docs"))
+}
+
+fn deploy_install_script() -> Step<Use> {
+    named::uses(
+        "cloudflare",
+        "wrangler-action",
+        "da0e0dfe58b7a431659754fdf3f186c529afbe65",
+    ) // v3
+    .add_with(("apiToken", vars::CLOUDFLARE_API_TOKEN))
+    .add_with(("accountId", vars::CLOUDFLARE_ACCOUNT_ID))
+    .add_with((
+        "command",
+        "r2 object put -f script/install.sh zed-open-source-website-assets/install.sh",
+    ))
+}
+
+fn deploy_docs_worker() -> Step<Use> {
+    named::uses(
+        "cloudflare",
+        "wrangler-action",
+        "da0e0dfe58b7a431659754fdf3f186c529afbe65",
+    ) // v3
+    .add_with(("apiToken", vars::CLOUDFLARE_API_TOKEN))
+    .add_with(("accountId", vars::CLOUDFLARE_ACCOUNT_ID))
+    .add_with(("command", "deploy .cloudflare/docs-proxy/src/worker.js"))
+}
+
+fn upload_wrangler_logs() -> Step<Use> {
+    named::uses(
+        "actions",
+        "upload-artifact",
+        "ea165f8d65b6e75b540449e92b4886f43607fa02",
+    ) // v4
+    .if_condition(Expression::new("always()"))
+    .add_with(("name", "wrangler_logs"))
+    .add_with(("path", "/home/runner/.config/.wrangler/logs/"))
+}
+
+fn docs_build_steps(job: Job) -> Job {
+    job.add_env(("DOCS_AMPLITUDE_API_KEY", vars::DOCS_AMPLITUDE_API_KEY))
+        .runs_on(runners::LINUX_XL)
+        .add_step(steps::checkout_repo())
+        .add_step(steps::setup_cargo_config(Platform::Linux))
+        .add_step(steps::cache_rust_dependencies_namespace())
+        .map(steps::install_linux_dependencies)
+        .add_step(steps::script("./script/generate-action-metadata"))
+        .add_step(lychee_link_check("./docs/src/**/*"))
+        .add_step(install_mdbook())
+        .add_step(build_docs_book())
+        .add_step(lychee_link_check("target/deploy/docs"))
+}
+
+pub(crate) fn check_docs() -> NamedJob {
+    NamedJob {
+        name: "check_docs".to_owned(),
+        job: docs_build_steps(release_job(&[])),
+    }
+}
+
+pub(crate) fn deploy_docs_job() -> NamedJob {
+    named::job(
+        docs_build_steps(
+            release_job(&[])
+                .name("Build and Deploy Docs")
+                .cond(Expression::new(
+                    "github.repository_owner == 'zed-industries'",
+                )),
+        )
+        .add_step(deploy_docs_to_pages())
+        .add_step(deploy_install_script())
+        .add_step(deploy_docs_worker())
+        .add_step(upload_wrangler_logs()),
+    )
+}
+
+pub(crate) fn deploy_docs() -> Workflow {
+    let deploy_docs = deploy_docs_job();
+
+    named::workflow()
+        .add_event(
+            Event::default().push(
+                Push::default()
+                    .add_branch("main")
+                    // todo! remove
+                    .add_branch("staged-docs-releases"),
+            ),
+        )
+        .add_job(deploy_docs.name, deploy_docs.job)
+}

tooling/xtask/src/tasks/workflows/run_tests.rs 🔗

@@ -10,6 +10,7 @@ use crate::tasks::workflows::{
 };
 
 use super::{
+    deploy_docs,
     runners::{self, Platform},
     steps::{self, FluentBuilder, NamedJob, named, release_job},
 };
@@ -51,7 +52,7 @@ pub(crate) fn run_tests() -> Workflow {
         should_run_tests.guard(doctests()),
         should_run_tests.guard(check_workspace_binaries()),
         should_run_tests.guard(check_dependencies()), // could be more specific here?
-        should_check_docs.guard(check_docs()),
+        should_check_docs.guard(deploy_docs::check_docs()),
         should_check_licences.guard(check_licenses()),
         should_check_scripts.guard(check_scripts()),
     ];
@@ -511,54 +512,6 @@ fn check_licenses() -> NamedJob {
     )
 }
 
-fn check_docs() -> NamedJob {
-    fn lychee_link_check(dir: &str) -> Step<Use> {
-        named::uses(
-            "lycheeverse",
-            "lychee-action",
-            "82202e5e9c2f4ef1a55a3d02563e1cb6041e5332",
-        ) // v2.4.1
-        .add_with(("args", format!("--no-progress --exclude '^http' '{dir}'")))
-        .add_with(("fail", true))
-        .add_with(("jobSummary", false))
-    }
-
-    fn install_mdbook() -> Step<Use> {
-        named::uses(
-            "peaceiris",
-            "actions-mdbook",
-            "ee69d230fe19748b7abf22df32acaa93833fad08", // v2
-        )
-        .with(("mdbook-version", "0.4.37"))
-    }
-
-    fn build_docs() -> Step<Run> {
-        named::bash(indoc::indoc! {r#"
-            mkdir -p target/deploy
-            mdbook build ./docs --dest-dir=../target/deploy/docs/
-        "#})
-    }
-
-    named::job(
-        release_job(&[])
-            .runs_on(runners::LINUX_LARGE)
-            .add_step(steps::checkout_repo())
-            .add_step(steps::setup_cargo_config(Platform::Linux))
-            // todo(ci): un-inline build_docs/action.yml here
-            .add_step(steps::cache_rust_dependencies_namespace())
-            .add_step(
-                lychee_link_check("./docs/src/**/*"), // check markdown links
-            )
-            .map(steps::install_linux_dependencies)
-            .add_step(steps::script("./script/generate-action-metadata"))
-            .add_step(install_mdbook())
-            .add_step(build_docs())
-            .add_step(
-                lychee_link_check("target/deploy/docs"), // check links in generated html
-            ),
-    )
-}
-
 pub(crate) fn check_scripts() -> NamedJob {
     fn download_actionlint() -> Step<Run> {
         named::bash(

tooling/xtask/src/tasks/workflows/vars.rs 🔗

@@ -51,6 +51,9 @@ secret!(SLACK_WEBHOOK_WORKFLOW_FAILURES);
 secret!(R2_ACCOUNT_ID);
 secret!(R2_ACCESS_KEY_ID);
 secret!(R2_SECRET_ACCESS_KEY);
+secret!(CLOUDFLARE_API_TOKEN);
+secret!(CLOUDFLARE_ACCOUNT_ID);
+secret!(DOCS_AMPLITUDE_API_KEY);
 
 // todo(ci) make these secrets too...
 var!(AZURE_SIGNING_ACCOUNT_NAME);