diff --git a/.github/workflows/after_release.yml b/.github/workflows/after_release.yml index ab2220764861b17317f1fa3971ecf2aa9b645c8d..c28763cfb7fd58c78b4bfb56904bbc8d4c3c880d 100644 --- a/.github/workflows/after_release.yml +++ b/.github/workflows/after_release.yml @@ -34,6 +34,116 @@ jobs: run: ./script/redeploy-vercel env: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + deploy_docs: + 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 }} + MDBOOK_BOOK__SITE_URL: ${{ steps.resolve-channel.outputs.site_url }} + DOCS_CHANNEL: ${{ steps.resolve-channel.outputs.channel }} + steps: + - id: resolve-channel + name: deploy_docs::resolve_channel_step + run: | + if [ -z "$CHANNEL" ]; then + if [ "$GITHUB_REF" = "refs/heads/main" ]; then + CHANNEL="nightly" + else + echo "::error::channel input is required when ref is not main." + exit 1 + fi + fi + + case "$CHANNEL" in + "nightly") + SITE_URL="/docs/nightly/" + PROJECT_NAME="docs-nightly" + ;; + "preview") + SITE_URL="/docs/preview/" + PROJECT_NAME="docs-preview" + ;; + "stable") + SITE_URL="/docs/" + PROJECT_NAME="docs" + ;; + *) + echo "::error::Invalid docs channel '$CHANNEL'. Expected one of: nightly, preview, stable." + exit 1 + ;; + esac + + echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT" + echo "site_url=$SITE_URL" >> "$GITHUB_OUTPUT" + echo "project_name=$PROJECT_NAME" >> "$GITHUB_OUTPUT" + env: + CHANNEL: ${{ (github.event.release.prerelease || inputs.prerelease) && 'preview' || 'stable' }} + - name: steps::checkout_repo + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd + with: + clean: false + ref: ${{ github.event.release.tag_name || inputs.tag_name }} + - 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@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 + with: + cache: rust + path: ~/.rustup + - name: steps::setup_linux + run: ./script/linux + - 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::docs_deploy_steps::deploy_to_cf_pages + uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy target/deploy --project-name=${{ steps.resolve-channel.outputs.project_name }} + - name: deploy_docs::docs_deploy_steps::upload_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::docs_deploy_steps::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::docs_deploy_steps::upload_wrangler_logs + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: wrangler_logs + path: /home/runner/.config/.wrangler/logs/ + timeout-minutes: 60 post_to_discord: needs: - rebuild_releases_page @@ -124,6 +234,7 @@ jobs: notify_on_failure: needs: - rebuild_releases_page + - deploy_docs - post_to_discord - publish_winget - create_sentry_release diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index 73543f004f6748929c59a3a40068fabd097e62a9..d665506b52e3496250ecad5c8ce383949161b73c 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -2,29 +2,6 @@ # Rebuild with `cargo xtask workflows`. name: deploy_docs on: - push: - branches: - - main - workflow_call: - inputs: - channel: - description: channel - type: string - default: '' - commit_sha: - description: commit_sha - type: string - default: '' - secrets: - DOCS_AMPLITUDE_API_KEY: - description: DOCS_AMPLITUDE_API_KEY - required: true - CLOUDFLARE_API_TOKEN: - description: CLOUDFLARE_API_TOKEN - required: true - CLOUDFLARE_ACCOUNT_ID: - description: CLOUDFLARE_ACCOUNT_ID - required: true workflow_dispatch: inputs: channel: @@ -46,7 +23,7 @@ jobs: DOCS_CHANNEL: ${{ steps.resolve-channel.outputs.channel }} steps: - id: resolve-channel - name: deploy_docs::deploy_docs_job::resolve_channel_step + name: deploy_docs::resolve_channel_step run: | if [ -z "$CHANNEL" ]; then if [ "$GITHUB_REF" = "refs/heads/main" ]; then @@ -80,7 +57,7 @@ jobs: echo "site_url=$SITE_URL" >> "$GITHUB_OUTPUT" echo "project_name=$PROJECT_NAME" >> "$GITHUB_OUTPUT" env: - CHANNEL: ${ inputs.channel } + CHANNEL: inputs.channel - name: steps::checkout_repo uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5bc4a405a0de85ca0bb47c40999d1e4365255eb4..17e121b9958db65a3f49c7e9e481153e84372673 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -725,20 +725,6 @@ jobs: run: gh release edit "$GITHUB_REF_NAME" --repo=zed-industries/zed --draft=false env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - deploy_docs: - needs: - - validate_release_assets - - create_draft_release - permissions: - contents: read - uses: zed-industries/zed/.github/workflows/deploy_docs.yml@main - secrets: - DOCS_AMPLITUDE_API_KEY: ${{ secrets.DOCS_AMPLITUDE_API_KEY }} - CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} - CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - with: - channel: ${{ endsWith(github.ref_name, '-pre') && 'preview' || 'stable' }} - commit_sha: ${{ github.sha }} push_release_update_notification: needs: - create_draft_release diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index 170abda73207eebc3f07be0622077365f11f0f8c..0000000000000000000000000000000000000000 --- a/PLAN.md +++ /dev/null @@ -1,219 +0,0 @@ -# Staged Docs Releases Plan - -## Background & Current State - -| Component | Status | Location | -|---|---|---| -| Docs build (CI check) | **xtask-generated** (in `run_tests.rs`) | `check_docs()` at L514–560 | -| Docs deploy workflow | **Hand-written YAML** | `.github/workflows/deploy_cloudflare.yml` | -| Composite build action | **Hand-written YAML** | `.github/actions/build_docs/action.yml` | -| Docs-proxy worker | **Runtime JS** | `.cloudflare/docs-proxy/src/worker.js` | -| book.toml | **Config** | `docs/book.toml` (site-url = `/docs/`) | - -There's already a TODO in the codebase acknowledging the duplication: - -``` -// todo(ci): un-inline build_docs/action.yml here -``` -(`tooling/xtask/src/tasks/workflows/run_tests.rs` L549) - ---- - -## Step 1: Move Docs Build & Deploy into xtask Workflow Generation - -### 1.1 Create `deploy_docs.rs` with shared build helpers and deploy workflow - -Create `tooling/xtask/src/tasks/workflows/deploy_docs.rs`. This module owns all docs build and deploy logic and exports shared helpers used by both the new deploy workflow and `check_docs()` in `run_tests.rs`. - -**Shared helpers** — export as `pub(crate)`: - -```rust -pub(crate) fn lychee_link_check(dir: &str) -> Step { ... } -pub(crate) fn install_mdbook() -> Step { ... } -pub(crate) fn build_docs_book() -> Step { ... } -``` - -Copy each implementation verbatim from the inline private functions currently inside `check_docs()` in `run_tests.rs`. - -**Build job** — mirror `.github/actions/build_docs/action.yml` step-for-step, using the patterns from `check_docs()` in `run_tests.rs` as the reference for how shared steps are expressed in xtask. Steps in order: - -1. `steps::checkout_repo()` -2. A step that runs `cp ./.cargo/collab-config.toml ./.cargo/config.toml` — the deploy workflow uses `collab-config.toml` (not `ci-config.toml`), so this is distinct from `steps::setup_cargo_config` -3. `steps::cache_rust_dependencies_namespace()` -4. `steps::install_linux_dependencies` (covers `./script/linux`, `./script/install-mold`, `./script/download-wasi-sdk`) -5. `steps::script("./script/generate-action-metadata")` -6. `lychee_link_check("./docs/src/**/*")` — check Markdown links -7. `install_mdbook()` -8. `build_docs_book()` -9. `lychee_link_check("target/deploy/docs")` — check links in generated HTML - -Set `DOCS_AMPLITUDE_API_KEY` on the build job (currently passed via `env:` to the composite action in `deploy_cloudflare.yml`). - -### 1.1.1 -**Deploy job** — copy each step verbatim from the `deploy-docs` job in `deploy_cloudflare.yml`. Steps in order: - -1. Wrangler: `pages deploy target/deploy --project-name=docs` -2. Wrangler: `r2 object put -f script/install.sh zed-open-source-website-assets/install.sh` -3. Wrangler: `deploy .cloudflare/docs-proxy/src/worker.js` -4. Upload Wrangler logs artifact (`always()`, path `~/.config/.wrangler/logs/`, name `wrangler_logs`) - -Note: steps "Deploy Docs Workers" and "Deploy Install Workers" in `deploy_cloudflare.yml` run the identical `wrangler deploy .cloudflare/docs-proxy/src/worker.js` command — this is a copy-paste bug. Include it only once (step 3 above). - -Each Wrangler step uses `cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65` with `apiToken` and `accountId` from `vars::CLOUDFLARE_API_TOKEN` and `vars::CLOUDFLARE_ACCOUNT_ID`. - -**Update `check_docs()`** — once the module exists, replace the inline private `lychee_link_check`, `install_mdbook`, and `build_docs` functions in `run_tests.rs` with calls to `deploy_docs::lychee_link_check`, `deploy_docs::install_mdbook`, and `deploy_docs::build_docs_book`. This resolves the TODO at L549. - -### 1.2 Register the new workflow - -In `tooling/xtask/src/tasks/workflows.rs`: -- Add `mod deploy_docs;` -- Add `WorkflowFile::zed(deploy_docs::deploy_docs)` to the workflows array - -### 1.3 Add Cloudflare secrets to `vars.rs` - -Add typed secret references: - -```rust -secret!(CLOUDFLARE_API_TOKEN); -secret!(CLOUDFLARE_ACCOUNT_ID); -secret!(DOCS_AMPLITUDE_API_KEY); -``` - -### 1.4 Verify generated output matches the hand-written workflow - -- Run `cargo xtask workflows` to generate `.github/workflows/deploy_docs.yml` -- Diff the generated file against `.github/workflows/deploy_cloudflare.yml` and `.github/actions/build_docs/action.yml` to confirm all steps, env vars, secrets, triggers, and job dependencies are equivalent -- Pay attention to: step ordering, `if:` conditions, artifact names, the Wrangler action hash, and that the duplicate worker deploy step is now deduplicated - -### 1.5 Ask the user to approve the generated files - -**Stop and show the generated `.github/workflows/deploy_docs.yml` to the user.** Ask them to confirm the output looks correct before proceeding to delete the hand-written files. Do not continue to step 1.6 without explicit approval. - -### 1.6 Delete hand-written files - -- Delete `.github/workflows/deploy_cloudflare.yml` (replaced by the generated workflow) -- Delete `.github/actions/build_docs/action.yml` (steps are now inlined in xtask) - -### 1.7 Final check - -The CI self-check (`check_xtask_workflows`) will enforce that the generated file stays in sync going forward. - ---- - -## Step 2: Split Deployments into Nightly, Preview, and Stable - -### 2.1 Introduce `DocsChannel` and parameterize the build - -Add a `DocsChannel` enum to `deploy_docs.rs`: - -```rust -pub(crate) enum DocsChannel { - Nightly, // site-url = "/docs/nightly/", project = "docs-nightly" - Preview, // site-url = "/docs/preview/", project = "docs-preview" - Stable, // site-url = "/docs/", project = "docs" -} -``` - -mdBook supports overriding `book.toml` values at build time via `MDBOOK_`-prefixed environment variables, using `__` for TOML key nesting. The `site-url` field lives under `[book]`, so setting `MDBOOK_BOOK__SITE_URL=/docs/nightly/` before `mdbook build` overrides it without touching the file. The `book.toml` in the repository remains unchanged at `site-url = "/docs/"`. - -The `build_docs_book()` step stays as-is; the channel env var is applied to the build job: - -```rust -fn build_job(channel: DocsChannel, deps: &[&NamedJob]) -> NamedJob { - // ... - .add_env(("MDBOOK_BOOK__SITE_URL", channel.site_url())) -} -``` - -The deploy step uses `--project-name` matching the channel: - -```rust -fn pages_deploy_step(channel: &DocsChannel) -> Step { - // wrangler: pages deploy target/deploy --project-name= -} -``` - -Export `pub(crate) fn deploy_docs_job(channel: DocsChannel, deps: &[&NamedJob]) -> NamedJob` for use in `release.rs`. - -### 2.2 Create `deploy_docs_nightly.rs` - -Create `tooling/xtask/src/tasks/workflows/deploy_docs_nightly.rs`. This is the standalone workflow for nightly docs, triggered on push to `main`. It calls `deploy_docs::deploy_docs_job(DocsChannel::Nightly, &[])`. The deploy job includes the `install.sh` R2 upload and docs-proxy worker deploy (these are `main`-push operations, currently bundled in `deploy_cloudflare.yml`). - -Register it in `workflows.rs`: `WorkflowFile::zed(deploy_docs_nightly::deploy_docs_nightly)`. - -### 2.3 Add preview and stable deploy jobs to `release.rs` - -In `release.rs`, call `deploy_docs::deploy_docs_job` twice after `validate_release_assets` completes: - -```rust -let deploy_docs_preview = deploy_docs::deploy_docs_job( - DocsChannel::Preview, - &[&validate_release_assets], -); -let deploy_docs_stable = deploy_docs::deploy_docs_job( - DocsChannel::Stable, - &[&validate_release_assets], -); -``` - -Apply an `if:` condition to each job: -- Preview: `startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-pre')` -- Stable: `startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-pre')` - -Add both jobs to the release workflow with `.add_job(...)`. - -### 2.4 Update the docs-proxy worker - -Modify `.cloudflare/docs-proxy/src/worker.js` to route all three channels: - -```javascript -export default { - async fetch(request, _env, _ctx) { - const url = new URL(request.url); - - let hostname; - if (url.pathname.startsWith("/docs/nightly")) { - hostname = "docs-nightly.pages.dev"; - } else if (url.pathname.startsWith("/docs/preview")) { - hostname = "docs-preview.pages.dev"; - } else { - hostname = "docs-anw.pages.dev"; - } - - url.hostname = hostname; - let res = await fetch(url, request); - - if (res.status === 404) { - res = await fetch("https://zed.dev/404"); - } - - return res; - }, -}; -``` - -The `docs-nightly` and `docs-preview` Pages project hostnames will be auto-assigned by Cloudflare on first deploy — verify the actual `*.pages.dev` hostnames and update accordingly. - -**Important:** Confirm no existing stable docs pages have a path starting with `nightly` or `preview` — grep `docs/src/SUMMARY.md` to verify. - -### 2.5 Wire install.sh and worker deploys - -- **install.sh R2 upload** → stays in the nightly workflow (runs on push to `main`, matching current behavior) -- **docs-proxy worker deploy** → stays in the nightly workflow (worker routes all three channels, deploying once on `main` push is sufficient) - ---- - -### 2.6 Add `noindex` meta tag for nightly and preview - -Also set a `DOCS_CHANNEL` env var (`nightly`, `preview`, or `stable`) on the build job alongside `MDBOOK_BOOK__SITE_URL` in step 2.1. Add a `channel_name() -> &'static str` method to `DocsChannel` returning the appropriate string. - -In `docs/theme/index.hbs`, add a `#noindex#` placeholder in `` directly after the existing `{{#if is_print}}` noindex block: - -```html -#noindex# -``` - -In `crates/docs_preprocessor/src/main.rs`'s `handle_postprocessing()`, read `DOCS_CHANNEL` and replace the placeholder — following the same pattern as the existing `#amplitude_key#` and `#description#` replacements: - -- `nightly` or `preview`: replace `#noindex#` with `` -- anything else: replace `#noindex#` with an empty string diff --git a/tooling/xtask/src/tasks/workflows/after_release.rs b/tooling/xtask/src/tasks/workflows/after_release.rs index 07ff1fba0d4799c463128362ad4ba996ccf8cea0..785a9286c2cd005274d71e327fc300d1570da64a 100644 --- a/tooling/xtask/src/tasks/workflows/after_release.rs +++ b/tooling/xtask/src/tasks/workflows/after_release.rs @@ -1,6 +1,7 @@ use gh_workflow::*; use crate::tasks::workflows::{ + deploy_docs, release::{self, notify_on_failure}, runners, steps::{CommonJobConditions, NamedJob, checkout_repo, dependant_job, named}, @@ -10,6 +11,8 @@ use crate::tasks::workflows::{ const TAG_NAME: &str = "${{ github.event.release.tag_name || inputs.tag_name }}"; const IS_PRERELEASE: &str = "${{ github.event.release.prerelease || inputs.prerelease }}"; const RELEASE_BODY: &str = "${{ github.event.release.body || inputs.body }}"; +const DOCS_CHANNEL: &str = + "${{ (github.event.release.prerelease || inputs.prerelease) && 'preview' || 'stable' }}"; pub fn after_release() -> Workflow { let tag_name = WorkflowInput::string("tag_name", None); @@ -17,11 +20,13 @@ pub fn after_release() -> Workflow { let body = WorkflowInput::string("body", Some(String::new())); let refresh_zed_dev = rebuild_releases_page(); + let deploy_docs = deploy_docs::release_docs_job(DOCS_CHANNEL, TAG_NAME); let post_to_discord = post_to_discord(&[&refresh_zed_dev]); let publish_winget = publish_winget(); let create_sentry_release = create_sentry_release(); let notify_on_failure = notify_on_failure(&[ &refresh_zed_dev, + &deploy_docs, &post_to_discord, &publish_winget, &create_sentry_release, @@ -37,6 +42,7 @@ pub fn after_release() -> Workflow { .add_input(body.name, body.input()), )) .add_job(refresh_zed_dev.name, refresh_zed_dev.job) + .add_job(deploy_docs.name, deploy_docs.job) .add_job(post_to_discord.name, post_to_discord.job) .add_job(publish_winget.name, publish_winget.job) .add_job(create_sentry_release.name, create_sentry_release.job) diff --git a/tooling/xtask/src/tasks/workflows/deploy_docs.rs b/tooling/xtask/src/tasks/workflows/deploy_docs.rs index ad6023c4d3439ea73f4dd88f4ea5299b88ad3d01..7f90c64f2dc9bcb740c9f3aa164d41dfda09c390 100644 --- a/tooling/xtask/src/tasks/workflows/deploy_docs.rs +++ b/tooling/xtask/src/tasks/workflows/deploy_docs.rs @@ -1,7 +1,4 @@ -use gh_workflow::{ - Event, Expression, Job, Push, Run, Step, Use, Workflow, WorkflowCall, WorkflowCallSecret, - WorkflowDispatch, -}; +use gh_workflow::{Event, Expression, Job, Run, Step, Use, Workflow, WorkflowDispatch}; use crate::tasks::workflows::{ runners, @@ -167,64 +164,61 @@ pub(crate) fn check_docs() -> NamedJob { } } -pub(crate) fn deploy_docs_job( - channel_input: &WorkflowInput, - commit_sha_input: &WorkflowInput, -) -> NamedJob { - fn resolve_channel_step( - channel_input: &WorkflowInput, - ) -> (Step, StepOutput, StepOutput, StepOutput) { - let step = named::bash(format!( - indoc::indoc! {r#" - if [ -z "$CHANNEL" ]; then - if [ "$GITHUB_REF" = "refs/heads/main" ]; then - CHANNEL="nightly" - else - echo "::error::channel input is required when ref is not main." - exit 1 - fi +fn resolve_channel_step( + channel_expr: impl Into, +) -> (Step, StepOutput, StepOutput, StepOutput) { + let step = Step::new("deploy_docs::resolve_channel_step").run(format!( + indoc::indoc! {r#" + if [ -z "$CHANNEL" ]; then + if [ "$GITHUB_REF" = "refs/heads/main" ]; then + CHANNEL="nightly" + else + echo "::error::channel input is required when ref is not main." + exit 1 fi + fi - case "$CHANNEL" in - "nightly") - SITE_URL="{nightly_site_url}" - PROJECT_NAME="{nightly_project_name}" - ;; - "preview") - SITE_URL="{preview_site_url}" - PROJECT_NAME="{preview_project_name}" - ;; - "stable") - SITE_URL="{stable_site_url}" - PROJECT_NAME="{stable_project_name}" - ;; - *) - echo "::error::Invalid docs channel '$CHANNEL'. Expected one of: nightly, preview, stable." - exit 1 - ;; - esac + case "$CHANNEL" in + "nightly") + SITE_URL="{nightly_site_url}" + PROJECT_NAME="{nightly_project_name}" + ;; + "preview") + SITE_URL="{preview_site_url}" + PROJECT_NAME="{preview_project_name}" + ;; + "stable") + SITE_URL="{stable_site_url}" + PROJECT_NAME="{stable_project_name}" + ;; + *) + echo "::error::Invalid docs channel '$CHANNEL'. Expected one of: nightly, preview, stable." + exit 1 + ;; + esac - echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT" - echo "site_url=$SITE_URL" >> "$GITHUB_OUTPUT" - echo "project_name=$PROJECT_NAME" >> "$GITHUB_OUTPUT" - "#}, - nightly_site_url = DocsChannel::Nightly.site_url(), - preview_site_url = DocsChannel::Preview.site_url(), - stable_site_url = DocsChannel::Stable.site_url(), - nightly_project_name = DocsChannel::Nightly.project_name(), - preview_project_name = DocsChannel::Preview.project_name(), - stable_project_name = DocsChannel::Stable.project_name(), - )) - .id("resolve-channel") - .add_env(("CHANNEL", channel_input.expr())) - ; + echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT" + echo "site_url=$SITE_URL" >> "$GITHUB_OUTPUT" + echo "project_name=$PROJECT_NAME" >> "$GITHUB_OUTPUT" + "#}, + nightly_site_url = DocsChannel::Nightly.site_url(), + preview_site_url = DocsChannel::Preview.site_url(), + stable_site_url = DocsChannel::Stable.site_url(), + nightly_project_name = DocsChannel::Nightly.project_name(), + preview_project_name = DocsChannel::Preview.project_name(), + stable_project_name = DocsChannel::Stable.project_name(), + )) + .id("resolve-channel") + .add_env(("CHANNEL", channel_expr.into())); - let channel = StepOutput::new(&step, "channel"); - let site_url = StepOutput::new(&step, "site_url"); - let project_name = StepOutput::new(&step, "project_name"); - (step, channel, site_url, project_name) - } - let (resolve_step, channel, site_url, project_name) = resolve_channel_step(channel_input); + let channel = StepOutput::new(&step, "channel"); + let site_url = StepOutput::new(&step, "site_url"); + let project_name = StepOutput::new(&step, "project_name"); + (step, channel, site_url, project_name) +} + +fn docs_job(channel_expr: impl Into, checkout_ref: Option) -> NamedJob { + let (resolve_step, channel, site_url, project_name) = resolve_channel_step(channel_expr); NamedJob { name: "deploy_docs".to_owned(), @@ -236,11 +230,7 @@ pub(crate) fn deploy_docs_job( "github.repository_owner == 'zed-industries'", )) .add_step(resolve_step), - Some(format!( - "${{{{ {} != '' && {} || github.sha }}}}", - commit_sha_input.expr(), - commit_sha_input.expr() - )), + checkout_ref, channel.to_string(), site_url.to_string(), ), @@ -249,6 +239,27 @@ pub(crate) fn deploy_docs_job( } } +pub(crate) fn release_docs_job( + channel_expr: impl Into, + checkout_ref: impl Into, +) -> NamedJob { + docs_job(channel_expr, Some(checkout_ref.into())) +} + +pub(crate) fn deploy_docs_job( + channel_input: &WorkflowInput, + commit_sha_input: &WorkflowInput, +) -> NamedJob { + docs_job( + channel_input.expr(), + Some(format!( + "${{{{ {} != '' && {} || github.sha }}}}", + commit_sha_input.expr(), + commit_sha_input.expr() + )), + ) +} + pub(crate) fn deploy_docs() -> Workflow { let channel = WorkflowInput::string("channel", Some(String::new())) .description("Docs channel to deploy: nightly, preview, or stable"); @@ -258,44 +269,10 @@ pub(crate) fn deploy_docs() -> Workflow { let deploy_docs = deploy_docs_job(&channel, &commit_sha); named::workflow() - .add_event( - Event::default() - .push(Push::default().add_branch("main")) - .workflow_dispatch( - WorkflowDispatch::default() - .add_input(channel.name, channel.input()) - .add_input(commit_sha.name, commit_sha.input()), - ), - ) - .add_event( - Event::default().workflow_call( - WorkflowCall::default() - .add_input(channel.name, channel.call_input()) - .add_input(commit_sha.name, commit_sha.call_input()) - .secrets([ - ( - "DOCS_AMPLITUDE_API_KEY".to_owned(), - WorkflowCallSecret { - description: "DOCS_AMPLITUDE_API_KEY".to_owned(), - required: true, - }, - ), - ( - "CLOUDFLARE_API_TOKEN".to_owned(), - WorkflowCallSecret { - description: "CLOUDFLARE_API_TOKEN".to_owned(), - required: true, - }, - ), - ( - "CLOUDFLARE_ACCOUNT_ID".to_owned(), - WorkflowCallSecret { - description: "CLOUDFLARE_ACCOUNT_ID".to_owned(), - required: true, - }, - ), - ]), - ), - ) + .on(Event::default().workflow_dispatch( + WorkflowDispatch::default() + .add_input(channel.name, channel.input()) + .add_input(commit_sha.name, commit_sha.input()), + )) .add_job(deploy_docs.name, deploy_docs.job) } diff --git a/tooling/xtask/src/tasks/workflows/release.rs b/tooling/xtask/src/tasks/workflows/release.rs index df1e2799a3a213688e78c9fd2bfcecb4c5a2398a..76895a37e3da84798c9dc18db4e0bd8dedadf1a8 100644 --- a/tooling/xtask/src/tasks/workflows/release.rs +++ b/tooling/xtask/src/tasks/workflows/release.rs @@ -1,7 +1,4 @@ -use gh_workflow::{ - Event, Expression, Input, Job, Level, Permissions, Push, Run, Step, Use, UsesJob, Workflow, - ctx::Context, -}; +use gh_workflow::{Event, Expression, Push, Run, Step, Use, Workflow, ctx::Context}; use indoc::formatdoc; use crate::tasks::workflows::{ @@ -67,7 +64,6 @@ pub(crate) fn release() -> Workflow { ); let auto_release_preview = auto_release_preview(&[&validate_release_assets]); - let deploy_docs = deploy_docs(&[&validate_release_assets], &create_draft_release); let test_jobs = [ &macos_tests, @@ -113,7 +109,6 @@ pub(crate) fn release() -> Workflow { .add_job(upload_release_assets.name, upload_release_assets.job) .add_job(validate_release_assets.name, validate_release_assets.job) .add_job(auto_release_preview.name, auto_release_preview.job) - .add_job(deploy_docs.name, deploy_docs.job) .add_job(push_slack_notification.name, push_slack_notification.job) } @@ -375,50 +370,6 @@ fn auto_release_preview(deps: &[&NamedJob]) -> NamedJob { ) } -fn deploy_docs(deps: &[&NamedJob], create_draft_release: &NamedJob) -> NamedJob { - let job = Job::default() - .needs( - deps.iter() - .map(|job| job.name.clone()) - .chain(std::iter::once(create_draft_release.name.clone())) - .collect::>(), - ) - .permissions(Permissions::default().contents(Level::Read)) - .uses( - "zed-industries", - "zed", - ".github/workflows/deploy_docs.yml", - "main", - ) - .with( - Input::default() - .add( - "channel", - "${{ endsWith(github.ref_name, '-pre') && 'preview' || 'stable' }}", - ) - .add("commit_sha", "${{ github.sha }}"), - ) - .secrets(indexmap::IndexMap::from([ - ( - "DOCS_AMPLITUDE_API_KEY".to_owned(), - vars::DOCS_AMPLITUDE_API_KEY.to_owned(), - ), - ( - "CLOUDFLARE_API_TOKEN".to_owned(), - vars::CLOUDFLARE_API_TOKEN.to_owned(), - ), - ( - "CLOUDFLARE_ACCOUNT_ID".to_owned(), - vars::CLOUDFLARE_ACCOUNT_ID.to_owned(), - ), - ])); - - NamedJob { - name: "deploy_docs".to_owned(), - job, - } -} - pub(crate) fn download_workflow_artifacts() -> Step { named::uses( "actions",