diff --git a/.cloudflare/README.md b/.cloudflare/README.md
index d21377ddffd..8da1a129fee 100644
--- a/.cloudflare/README.md
+++ b/.cloudflare/README.md
@@ -4,11 +4,11 @@ from Cloudflare.
- `open-source-website-assets` is used for `install.sh`
- `docs-proxy` is used for `https://zed.dev/docs`
-On push to `main`, both of these (and the files they depend on) are uploaded to Cloudflare.
+During docs deployments, both of these (and the files they depend on) are uploaded to Cloudflare.
### Deployment
-These functions are deployed on push to main by the deploy_cloudflare.yml workflow. Worker Rules in Cloudflare intercept requests to zed.dev and proxy them to the appropriate workers.
+These functions are deployed by the docs deployment workflows. Worker Rules in Cloudflare intercept requests to zed.dev and proxy them to the appropriate workers.
### Testing
diff --git a/.cloudflare/docs-proxy/src/worker.js b/.cloudflare/docs-proxy/src/worker.js
index f9f441883ad..08b0265fafb 100644
--- a/.cloudflare/docs-proxy/src/worker.js
+++ b/.cloudflare/docs-proxy/src/worker.js
@@ -1,7 +1,22 @@
export default {
async fetch(request, _env, _ctx) {
const url = new URL(request.url);
- url.hostname = "docs-anw.pages.dev";
+
+ if (url.pathname === "/docs/nightly") {
+ url.hostname = "docs-nightly.pages.dev";
+ url.pathname = "/docs/";
+ } else if (url.pathname.startsWith("/docs/nightly/")) {
+ url.hostname = "docs-nightly.pages.dev";
+ url.pathname = url.pathname.replace("/docs/nightly/", "/docs/");
+ } else if (url.pathname === "/docs/preview") {
+ url.hostname = "docs-preview-5xd.pages.dev";
+ url.pathname = "/docs/";
+ } else if (url.pathname.startsWith("/docs/preview/")) {
+ url.hostname = "docs-preview-5xd.pages.dev";
+ url.pathname = url.pathname.replace("/docs/preview/", "/docs/");
+ } else {
+ url.hostname = "docs-anw.pages.dev";
+ }
let res = await fetch(url, request);
diff --git a/.github/actions/build_docs/action.yml b/.github/actions/build_docs/action.yml
deleted file mode 100644
index 002f6f4653f..00000000000
--- a/.github/actions/build_docs/action.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: "Build docs"
-description: "Build the docs"
-
-runs:
- using: "composite"
- steps:
- - name: Setup mdBook
- uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08 # v2
- with:
- mdbook-version: "0.4.37"
-
- - name: Cache dependencies
- uses: swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2
- with:
- save-if: ${{ github.ref == 'refs/heads/main' }}
- # cache-provider: "buildjet"
-
- - name: Install Linux dependencies
- shell: bash -euxo pipefail {0}
- run: ./script/linux
-
- - name: Download WASI SDK
- shell: bash -euxo pipefail {0}
- run: ./script/download-wasi-sdk
-
- - name: Generate action metadata
- shell: bash -euxo pipefail {0}
- run: ./script/generate-action-metadata
-
- - name: Check for broken links (in MD)
- uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 # v2.4.1
- with:
- args: --no-progress --exclude '^http' './docs/src/**/*'
- fail: true
-
- - name: Build book
- shell: bash -euxo pipefail {0}
- run: |
- mkdir -p target/deploy
- mdbook build ./docs --dest-dir=../target/deploy/docs/
-
- - name: Check for broken links (in HTML)
- uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 # v2.4.1
- with:
- args: --no-progress --exclude '^http' 'target/deploy/docs/'
- fail: true
diff --git a/.github/workflows/after_release.yml b/.github/workflows/after_release.yml
index ab222076486..f6777aa2c00 100644
--- a/.github/workflows/after_release.yml
+++ b/.github/workflows/after_release.yml
@@ -1,6 +1,9 @@
# Generated from xtask::workflows::after_release
# Rebuild with `cargo xtask workflows`.
name: after_release
+env:
+ TAG_NAME: ${{ github.event.release.tag_name || inputs.tag_name }}
+ IS_PRERELEASE: ${{ github.event.release.prerelease || inputs.prerelease }}
on:
release:
types:
@@ -25,7 +28,7 @@ jobs:
runs-on: namespace-profile-2x4-ubuntu-2404
steps:
- name: after_release::rebuild_releases_page::refresh_cloud_releases
- run: curl -fX POST https://cloud.zed.dev/releases/refresh?expect_tag=${{ github.event.release.tag_name || inputs.tag_name }}
+ run: curl -fX POST "https://cloud.zed.dev/releases/refresh?expect_tag=$TAG_NAME"
- name: steps::checkout_repo
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
@@ -34,6 +37,18 @@ jobs:
run: ./script/redeploy-vercel
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
+ deploy_docs:
+ if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
+ 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: ${{ (github.event.release.prerelease || inputs.prerelease) && 'preview' || 'stable' }}
+ checkout_ref: ${{ github.event.release.tag_name || inputs.tag_name }}
post_to_discord:
needs:
- rebuild_releases_page
@@ -43,7 +58,7 @@ jobs:
- id: get-release-url
name: after_release::post_to_discord::get_release_url
run: |
- if [ "${{ github.event.release.prerelease || inputs.prerelease }}" == "true" ]; then
+ if [ "$IS_PRERELEASE" == "true" ]; then
URL="https://zed.dev/releases/preview"
else
URL="https://zed.dev/releases/stable"
@@ -55,7 +70,7 @@ jobs:
uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757
with:
stringToTruncate: |
- 📣 Zed [${{ github.event.release.tag_name || inputs.tag_name }}](<${{ steps.get-release-url.outputs.URL }}>) was just released!
+ 📣 Zed [${{ env.TAG_NAME }}](<${{ steps.get-release-url.outputs.URL }}>) was just released!
${{ github.event.release.body || inputs.body }}
maxLength: 2000
@@ -90,7 +105,7 @@ jobs:
- id: set-package-name
name: after_release::publish_winget::set_package_name
run: |
- if ("${{ github.event.release.prerelease || inputs.prerelease }}" -eq "true") {
+ if ($env:IS_PRERELEASE -eq "true") {
$PACKAGE_NAME = "ZedIndustries.Zed.Preview"
} else {
$PACKAGE_NAME = "ZedIndustries.Zed"
@@ -102,7 +117,7 @@ jobs:
uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f
with:
identifier: ${{ steps.set-package-name.outputs.PACKAGE_NAME }}
- release-tag: ${{ github.event.release.tag_name || inputs.tag_name }}
+ release-tag: ${{ env.TAG_NAME }}
max-versions-to-keep: 5
token: ${{ secrets.WINGET_TOKEN }}
create_sentry_release:
@@ -127,6 +142,7 @@ jobs:
- post_to_discord
- publish_winget
- create_sentry_release
+ - deploy_docs
if: failure()
runs-on: namespace-profile-2x4-ubuntu-2404
steps:
diff --git a/.github/workflows/deploy_cloudflare.yml b/.github/workflows/deploy_cloudflare.yml
deleted file mode 100644
index 4e029c63ccd..00000000000
--- a/.github/workflows/deploy_cloudflare.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-name: Deploy Docs
-
-on:
- push:
- branches:
- - main
-
-jobs:
- deploy-docs:
- name: Deploy Docs
- if: github.repository_owner == 'zed-industries'
- runs-on: namespace-profile-16x32-ubuntu-2204
-
- steps:
- - name: Checkout repo
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- with:
- clean: false
-
- - name: Set up default .cargo/config.toml
- run: cp ./.cargo/collab-config.toml ./.cargo/config.toml
-
- - name: Build docs
- uses: ./.github/actions/build_docs
- env:
- CC: clang
- CXX: clang++
- DOCS_AMPLITUDE_API_KEY: ${{ secrets.DOCS_AMPLITUDE_API_KEY }}
- DOCS_CONSENT_IO_INSTANCE: ${{ secrets.DOCS_CONSENT_IO_INSTANCE }}
-
- - name: Deploy Docs
- uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3
- with:
- apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- command: pages deploy target/deploy --project-name=docs
-
- - name: Deploy Install
- uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3
- 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 Workers
- uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3
- with:
- apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- command: deploy .cloudflare/docs-proxy/src/worker.js
-
- - name: Deploy Install Workers
- uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3
- with:
- apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- command: deploy .cloudflare/docs-proxy/src/worker.js
-
- - name: Preserve Wrangler logs
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
- if: always()
- with:
- name: wrangler_logs
- path: /home/runner/.config/.wrangler/logs/
diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml
new file mode 100644
index 00000000000..1739b6b257a
--- /dev/null
+++ b/.github/workflows/deploy_docs.yml
@@ -0,0 +1,153 @@
+# Generated from xtask::workflows::deploy_docs
+# Rebuild with `cargo xtask workflows`.
+name: deploy_docs
+on:
+ workflow_call:
+ inputs:
+ channel:
+ description: channel
+ type: string
+ default: ''
+ checkout_ref:
+ description: checkout_ref
+ 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:
+ description: 'Docs channel to deploy: nightly, preview, or stable'
+ type: string
+ default: ''
+ checkout_ref:
+ description: Git ref to checkout and deploy. Defaults to event SHA when omitted.
+ type: string
+ default: ''
+jobs:
+ 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 }}
+ CC: clang
+ CXX: clang++
+ 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"
+ echo "site_url=$SITE_URL"
+ echo "project_name=$PROJECT_NAME"
+ } >> "$GITHUB_OUTPUT"
+ env:
+ CHANNEL: ${{ inputs.channel }}
+ - name: steps::checkout_repo
+ uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
+ with:
+ clean: false
+ ref: ${{ inputs.checkout_ref != '' && inputs.checkout_ref || github.sha }}
+ - 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/
+ env:
+ DOCS_CHANNEL: ${{ steps.resolve-channel.outputs.channel }}
+ MDBOOK_BOOK__SITE_URL: ${{ steps.resolve-channel.outputs.site_url }}
+ - 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 }} --branch main
+ - 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
+defaults:
+ run:
+ shell: bash -euxo pipefail {0}
diff --git a/.github/workflows/deploy_nightly_docs.yml b/.github/workflows/deploy_nightly_docs.yml
new file mode 100644
index 00000000000..340713e0a41
--- /dev/null
+++ b/.github/workflows/deploy_nightly_docs.yml
@@ -0,0 +1,23 @@
+# Generated from xtask::workflows::deploy_nightly_docs
+# Rebuild with `cargo xtask workflows`.
+name: deploy_nightly_docs
+on:
+ push:
+ branches:
+ - main
+jobs:
+ deploy_docs:
+ if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
+ 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: nightly
+ checkout_ref: ${{ github.sha }}
+defaults:
+ run:
+ shell: bash -euxo pipefail {0}
diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index 2051fa567b5..4ce9b3cc1d6 100644
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -637,8 +637,9 @@ jobs:
needs:
- orchestrate
if: needs.orchestrate.outputs.run_docs == 'true' && github.event_name != 'merge_group'
- runs-on: namespace-profile-8x16-ubuntu-2204
+ runs-on: namespace-profile-16x32-ubuntu-2204
env:
+ DOCS_AMPLITUDE_API_KEY: ${{ secrets.DOCS_AMPLITUDE_API_KEY }}
CC: clang
CXX: clang++
steps:
@@ -655,27 +656,30 @@ 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::download_wasi_sdk
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
+ env:
+ DOCS_CHANNEL: stable
+ MDBOOK_BOOK__SITE_URL: /docs/
+ - name: deploy_docs::lychee_link_check
uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332
with:
args: --no-progress --exclude '^http' 'target/deploy/docs'
diff --git a/crates/docs_preprocessor/src/main.rs b/crates/docs_preprocessor/src/main.rs
index 6655d86d25c..5b860ba16cd 100644
--- a/crates/docs_preprocessor/src/main.rs
+++ b/crates/docs_preprocessor/src/main.rs
@@ -679,6 +679,12 @@ fn handle_postprocessing() -> Result<()> {
.to_string();
let amplitude_key = std::env::var("DOCS_AMPLITUDE_API_KEY").unwrap_or_default();
let consent_io_instance = std::env::var("DOCS_CONSENT_IO_INSTANCE").unwrap_or_default();
+ let docs_channel = std::env::var("DOCS_CHANNEL").unwrap_or_else(|_| "stable".to_string());
+ let noindex = if docs_channel == "nightly" || docs_channel == "preview" {
+ ""
+ } else {
+ ""
+ };
output.insert("html".to_string(), zed_html);
mdbook::Renderer::render(&mdbook::renderer::HtmlHandlebars::new(), &ctx)?;
@@ -749,6 +755,7 @@ fn handle_postprocessing() -> Result<()> {
let contents = contents.replace("#description#", meta_description);
let contents = contents.replace("#amplitude_key#", &litude_key);
let contents = contents.replace("#consent_io_instance#", &consent_io_instance);
+ let contents = contents.replace("#noindex#", noindex);
let contents = title_regex()
.replace(&contents, |_: ®ex::Captures| {
format!("
{}", meta_title)
diff --git a/docs/theme/index.hbs b/docs/theme/index.hbs
index 24378bcca69..2c7786817aa 100644
--- a/docs/theme/index.hbs
+++ b/docs/theme/index.hbs
@@ -30,6 +30,7 @@
{{#if is_print }}
{{/if}}
+ #noindex#
{{#if base_url}}
{{/if}}
diff --git a/tooling/xtask/src/tasks/workflows.rs b/tooling/xtask/src/tasks/workflows.rs
index 2e21363bb65..b275503f34d 100644
--- a/tooling/xtask/src/tasks/workflows.rs
+++ b/tooling/xtask/src/tasks/workflows.rs
@@ -15,6 +15,7 @@ mod compare_perf;
mod compliance_check;
mod danger;
mod deploy_collab;
+mod deploy_docs;
mod extension_auto_bump;
mod extension_bump;
mod extension_tests;
@@ -203,6 +204,8 @@ pub fn run_workflows(args: GenerateWorkflowArgs) -> Result<()> {
WorkflowFile::zed(compliance_check::compliance_check),
WorkflowFile::zed(danger::danger),
WorkflowFile::zed(deploy_collab::deploy_collab),
+ WorkflowFile::zed(deploy_docs::deploy_docs),
+ WorkflowFile::zed(deploy_docs::deploy_nightly_docs),
WorkflowFile::zed(extension_bump::extension_bump),
WorkflowFile::zed(extension_auto_bump::extension_auto_bump),
WorkflowFile::zed(extension_tests::extension_tests),
diff --git a/tooling/xtask/src/tasks/workflows/after_release.rs b/tooling/xtask/src/tasks/workflows/after_release.rs
index 07ff1fba0d4..fe96325c7fd 100644
--- a/tooling/xtask/src/tasks/workflows/after_release.rs
+++ b/tooling/xtask/src/tasks/workflows/after_release.rs
@@ -1,15 +1,19 @@
use gh_workflow::*;
use crate::tasks::workflows::{
+ deploy_docs::deploy_docs_workflow_call,
release::{self, notify_on_failure},
runners,
steps::{CommonJobConditions, NamedJob, checkout_repo, dependant_job, named},
vars::{self, StepOutput, WorkflowInput},
};
-const TAG_NAME: &str = "${{ github.event.release.tag_name || inputs.tag_name }}";
-const IS_PRERELEASE: &str = "${{ github.event.release.prerelease || inputs.prerelease }}";
+const TAG_NAME_ENV: &str = "${{ github.event.release.tag_name || inputs.tag_name }}";
+const IS_PRERELEASE_ENV: &str = "${{ github.event.release.prerelease || inputs.prerelease }}";
+const TAG_NAME: &str = "${{ env.TAG_NAME }}";
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,17 +21,26 @@ 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_workflow_call(DOCS_CHANNEL, TAG_NAME_ENV);
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,
- &post_to_discord,
- &publish_winget,
- &create_sentry_release,
- ]);
+ let notify_on_failure = {
+ let notify_on_failure = notify_on_failure(&[
+ &refresh_zed_dev,
+ &post_to_discord,
+ &publish_winget,
+ &create_sentry_release,
+ ]);
+ NamedJob {
+ name: notify_on_failure.name,
+ job: notify_on_failure.job.add_need(deploy_docs.name.clone()),
+ }
+ };
named::workflow()
+ .add_env(("TAG_NAME", TAG_NAME_ENV))
+ .add_env(("IS_PRERELEASE", IS_PRERELEASE_ENV))
.on(Event::default()
.release(Release::default().types(vec![ReleaseType::Published]))
.workflow_dispatch(
@@ -37,6 +50,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)
@@ -45,9 +59,7 @@ pub fn after_release() -> Workflow {
fn rebuild_releases_page() -> NamedJob {
fn refresh_cloud_releases() -> Step {
- named::bash(format!(
- "curl -fX POST https://cloud.zed.dev/releases/refresh?expect_tag={TAG_NAME}"
- ))
+ named::bash("curl -fX POST \"https://cloud.zed.dev/releases/refresh?expect_tag=$TAG_NAME\"")
}
fn redeploy_zed_dev() -> Step {
@@ -66,16 +78,16 @@ fn rebuild_releases_page() -> NamedJob {
fn post_to_discord(deps: &[&NamedJob]) -> NamedJob {
fn get_release_url() -> Step {
- named::bash(format!(
- r#"if [ "{IS_PRERELEASE}" == "true" ]; then
+ named::bash(
+ r#"if [ "$IS_PRERELEASE" == "true" ]; then
URL="https://zed.dev/releases/preview"
else
URL="https://zed.dev/releases/stable"
fi
echo "URL=$URL" >> "$GITHUB_OUTPUT"
-"#
- ))
+"#,
+ )
.id("get-release-url")
}
@@ -136,17 +148,15 @@ fn publish_winget() -> NamedJob {
}
fn set_package_name() -> (Step, StepOutput) {
- let script = format!(
- r#"if ("{IS_PRERELEASE}" -eq "true") {{
+ let script = r#"if ($env:IS_PRERELEASE -eq "true") {
$PACKAGE_NAME = "ZedIndustries.Zed.Preview"
-}} else {{
+} else {
$PACKAGE_NAME = "ZedIndustries.Zed"
-}}
+}
echo "PACKAGE_NAME=$PACKAGE_NAME" >> $env:GITHUB_OUTPUT
-"#
- );
- let step = named::pwsh(&script).id("set-package-name");
+"#;
+ let step = named::pwsh(script).id("set-package-name");
let output = StepOutput::new(&step, "PACKAGE_NAME");
(step, output)
diff --git a/tooling/xtask/src/tasks/workflows/deploy_docs.rs b/tooling/xtask/src/tasks/workflows/deploy_docs.rs
new file mode 100644
index 00000000000..c2cb6331816
--- /dev/null
+++ b/tooling/xtask/src/tasks/workflows/deploy_docs.rs
@@ -0,0 +1,360 @@
+use gh_workflow::{
+ Event, Expression, Input, Job, Level, Permissions, Push, Run, Step, Use, UsesJob, Workflow,
+ WorkflowCall, WorkflowCallSecret, WorkflowDispatch,
+};
+
+use crate::tasks::workflows::{
+ runners,
+ steps::{self, CommonJobConditions, FluentBuilder as _, NamedJob, named, release_job},
+ vars::{self, StepOutput, WorkflowInput},
+};
+
+const BUILD_OUTPUT_DIR: &str = "target/deploy";
+
+pub(crate) enum DocsChannel {
+ Nightly,
+ Preview,
+ Stable,
+}
+
+impl DocsChannel {
+ pub(crate) fn site_url(&self) -> &'static str {
+ match self {
+ Self::Nightly => "/docs/nightly/",
+ Self::Preview => "/docs/preview/",
+ Self::Stable => "/docs/",
+ }
+ }
+
+ pub(crate) fn project_name(&self) -> &'static str {
+ match self {
+ Self::Nightly => "docs-nightly",
+ Self::Preview => "docs-preview",
+ Self::Stable => "docs",
+ }
+ }
+
+ pub(crate) fn channel_name(&self) -> &'static str {
+ match self {
+ Self::Nightly => "nightly",
+ Self::Preview => "preview",
+ Self::Stable => "stable",
+ }
+ }
+}
+
+pub(crate) fn lychee_link_check(dir: &str) -> Step