Detailed changes
@@ -0,0 +1,69 @@
+# Generated from xtask::workflows::after_release
+# Rebuild with `cargo xtask workflows`.
+name: after_release
+on:
+ release:
+ types:
+ - published
+jobs:
+ rebuild_releases_page:
+ if: github.repository_owner == 'zed-industries'
+ runs-on: namespace-profile-2x4-ubuntu-2404
+ steps:
+ - name: after_release::rebuild_releases_page
+ run: 'curl https://zed.dev/api/revalidate-releases -H "Authorization: Bearer ${RELEASE_NOTES_API_TOKEN}"'
+ shell: bash -euxo pipefail {0}
+ env:
+ RELEASE_NOTES_API_TOKEN: ${{ secrets.RELEASE_NOTES_API_TOKEN }}
+ post_to_discord:
+ needs:
+ - rebuild_releases_page
+ if: github.repository_owner == 'zed-industries'
+ runs-on: namespace-profile-2x4-ubuntu-2404
+ steps:
+ - id: get-release-url
+ name: after_release::post_to_discord::get_release_url
+ run: |
+ if [ "${{ github.event.release.prerelease }}" == "true" ]; then
+ URL="https://zed.dev/releases/preview"
+ else
+ URL="https://zed.dev/releases/stable"
+ fi
+
+ echo "URL=$URL" >> "$GITHUB_OUTPUT"
+ shell: bash -euxo pipefail {0}
+ - id: get-content
+ name: after_release::post_to_discord::get_content
+ uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757
+ with:
+ stringToTruncate: |
+ 📣 Zed [${{ github.event.release.tag_name }}](<${{ steps.get-release-url.outputs.URL }}>) was just released!
+
+ ${{ github.event.release.body }}
+ maxLength: 2000
+ truncationSymbol: '...'
+ - name: after_release::post_to_discord::discord_webhook_action
+ uses: tsickert/discord-webhook@c840d45a03a323fbc3f7507ac7769dbd91bfb164
+ with:
+ webhook-url: ${{ secrets.DISCORD_WEBHOOK_RELEASE_NOTES }}
+ content: ${{ steps.get-content.outputs.string }}
+ publish_winget:
+ runs-on: namespace-profile-2x4-ubuntu-2404
+ steps:
+ - id: set-package-name
+ name: after_release::publish_winget::set_package_name
+ run: |
+ if [ "${{ github.event.release.prerelease }}" == "true" ]; then
+ PACKAGE_NAME=ZedIndustries.Zed.Preview
+ else
+ PACKAGE_NAME=ZedIndustries.Zed
+ fi
+
+ echo "PACKAGE_NAME=$PACKAGE_NAME" >> "$GITHUB_OUTPUT"
+ shell: bash -euxo pipefail {0}
+ - name: after_release::publish_winget::winget_releaser
+ uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f
+ with:
+ identifier: ${{ steps.set-package-name.outputs.PACKAGE_NAME }}
+ max-versions-to-keep: 5
+ token: ${{ secrets.WINGET_TOKEN }}
@@ -1,93 +0,0 @@
-# IF YOU UPDATE THE NAME OF ANY GITHUB SECRET, YOU MUST CHERRY PICK THE COMMIT
-# TO BOTH STABLE AND PREVIEW CHANNELS
-
-name: Release Actions
-
-on:
- release:
- types: [published]
-
-jobs:
- discord_release:
- if: github.repository_owner == 'zed-industries'
- runs-on: ubuntu-latest
- steps:
- - name: Get release URL
- id: get-release-url
- run: |
- if [ "${{ github.event.release.prerelease }}" == "true" ]; then
- URL="https://zed.dev/releases/preview"
- else
- URL="https://zed.dev/releases/stable"
- fi
-
- echo "URL=$URL" >> "$GITHUB_OUTPUT"
- - name: Get content
- uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757 # v1.4.1
- id: get-content
- with:
- stringToTruncate: |
- 📣 Zed [${{ github.event.release.tag_name }}](<${{ steps.get-release-url.outputs.URL }}>) was just released!
-
- ${{ github.event.release.body }}
- maxLength: 2000
- truncationSymbol: "..."
- - name: Discord Webhook Action
- uses: tsickert/discord-webhook@c840d45a03a323fbc3f7507ac7769dbd91bfb164 # v5.3.0
- with:
- webhook-url: ${{ secrets.DISCORD_WEBHOOK_RELEASE_NOTES }}
- content: ${{ steps.get-content.outputs.string }}
-
- publish-winget:
- runs-on:
- - ubuntu-latest
- steps:
- - name: Set Package Name
- id: set-package-name
- run: |
- if [ "${{ github.event.release.prerelease }}" == "true" ]; then
- PACKAGE_NAME=ZedIndustries.Zed.Preview
- else
- PACKAGE_NAME=ZedIndustries.Zed
- fi
-
- echo "PACKAGE_NAME=$PACKAGE_NAME" >> "$GITHUB_OUTPUT"
- - uses: vedantmgoyal9/winget-releaser@19e706d4c9121098010096f9c495a70a7518b30f # v2
- with:
- identifier: ${{ steps.set-package-name.outputs.PACKAGE_NAME }}
- max-versions-to-keep: 5
- token: ${{ secrets.WINGET_TOKEN }}
-
- send_release_notes_email:
- if: false && github.repository_owner == 'zed-industries' && !github.event.release.prerelease
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- with:
- fetch-depth: 0
-
- - name: Check if release was promoted from preview
- id: check-promotion-from-preview
- run: |
- VERSION="${{ github.event.release.tag_name }}"
- PREVIEW_TAG="${VERSION}-pre"
-
- if git rev-parse "$PREVIEW_TAG" > /dev/null 2>&1; then
- echo "was_promoted_from_preview=true" >> "$GITHUB_OUTPUT"
- else
- echo "was_promoted_from_preview=false" >> "$GITHUB_OUTPUT"
- fi
-
- - name: Send release notes email
- if: steps.check-promotion-from-preview.outputs.was_promoted_from_preview == 'true'
- run: |
- TAG="${{ github.event.release.tag_name }}"
- cat << 'EOF' > release_body.txt
- ${{ github.event.release.body }}
- EOF
- jq -n --arg tag "$TAG" --rawfile body release_body.txt '{version: $tag, markdown_body: $body}' \
- > release_data.json
- curl -X POST "https://zed.dev/api/send_release_notes_email" \
- -H "Authorization: Bearer ${{ secrets.RELEASE_NOTES_API_TOKEN }}" \
- -H "Content-Type: application/json" \
- -d @release_data.json
@@ -20951,6 +20951,7 @@ dependencies = [
"gh-workflow",
"indexmap 2.11.4",
"indoc",
+ "serde",
"toml 0.8.23",
"toml_edit 0.22.27",
]
@@ -17,5 +17,6 @@ clap = { workspace = true, features = ["derive"] }
toml.workspace = true
indoc.workspace = true
indexmap.workspace = true
+serde.workspace = true
toml_edit.workspace = true
gh-workflow.workspace = true
@@ -3,6 +3,7 @@ use clap::Parser;
use std::fs;
use std::path::Path;
+mod after_release;
mod cherry_pick;
mod compare_perf;
mod danger;
@@ -33,6 +34,7 @@ pub fn run_workflows(_: GenerateWorkflowArgs) -> Result<()> {
("compare_perf.yml", compare_perf::compare_perf()),
("run_unit_evals.yml", run_agent_evals::run_unit_evals()),
("run_agent_evals.yml", run_agent_evals::run_agent_evals()),
+ ("after_release.yml", after_release::after_release()),
];
fs::create_dir_all(dir)
.with_context(|| format!("Failed to create directory: {}", dir.display()))?;
@@ -0,0 +1,123 @@
+use gh_workflow::*;
+
+use crate::tasks::workflows::{
+ runners,
+ steps::{NamedJob, dependant_job, named},
+ vars::{self, StepOutput},
+};
+
+pub fn after_release() -> Workflow {
+ let refresh_zed_dev = rebuild_releases_page();
+ let post_to_discord = post_to_discord(&[&refresh_zed_dev]);
+ let publish_winget = publish_winget();
+
+ named::workflow()
+ .on(Event::default().release(Release::default().types(vec![ReleaseType::Published])))
+ .add_job(refresh_zed_dev.name, refresh_zed_dev.job)
+ .add_job(post_to_discord.name, post_to_discord.job)
+ .add_job(publish_winget.name, publish_winget.job)
+}
+
+fn rebuild_releases_page() -> NamedJob {
+ named::job(
+ Job::default()
+ .runs_on(runners::LINUX_SMALL)
+ .cond(Expression::new(
+ "github.repository_owner == 'zed-industries'",
+ ))
+ .add_step(named::bash(
+ "curl https://zed.dev/api/revalidate-releases -H \"Authorization: Bearer ${RELEASE_NOTES_API_TOKEN}\"",
+ ).add_env(("RELEASE_NOTES_API_TOKEN", vars::RELEASE_NOTES_API_TOKEN))),
+ )
+}
+
+fn post_to_discord(deps: &[&NamedJob]) -> NamedJob {
+ fn get_release_url() -> Step<Run> {
+ named::bash(indoc::indoc! {r#"
+ if [ "${{ github.event.release.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")
+ }
+
+ fn get_content() -> Step<Use> {
+ named::uses(
+ "2428392",
+ "gh-truncate-string-action",
+ "b3ff790d21cf42af3ca7579146eedb93c8fb0757", // v1.4.1
+ )
+ .id("get-content")
+ .add_with((
+ "stringToTruncate",
+ indoc::indoc! {r#"
+ 📣 Zed [${{ github.event.release.tag_name }}](<${{ steps.get-release-url.outputs.URL }}>) was just released!
+
+ ${{ github.event.release.body }}
+ "#},
+ ))
+ .add_with(("maxLength", 2000))
+ .add_with(("truncationSymbol", "..."))
+ }
+
+ fn discord_webhook_action() -> Step<Use> {
+ named::uses(
+ "tsickert",
+ "discord-webhook",
+ "c840d45a03a323fbc3f7507ac7769dbd91bfb164", // v5.3.0
+ )
+ .add_with(("webhook-url", vars::DISCORD_WEBHOOK_RELEASE_NOTES))
+ .add_with(("content", "${{ steps.get-content.outputs.string }}"))
+ }
+ let job = dependant_job(deps)
+ .runs_on(runners::LINUX_SMALL)
+ .cond(Expression::new(
+ "github.repository_owner == 'zed-industries'",
+ ))
+ .add_step(get_release_url())
+ .add_step(get_content())
+ .add_step(discord_webhook_action());
+ named::job(job)
+}
+
+fn publish_winget() -> NamedJob {
+ fn set_package_name() -> (Step<Run>, StepOutput) {
+ let step = named::bash(indoc::indoc! {r#"
+ if [ "${{ github.event.release.prerelease }}" == "true" ]; then
+ PACKAGE_NAME=ZedIndustries.Zed.Preview
+ else
+ PACKAGE_NAME=ZedIndustries.Zed
+ fi
+
+ echo "PACKAGE_NAME=$PACKAGE_NAME" >> "$GITHUB_OUTPUT"
+ "#})
+ .id("set-package-name");
+
+ let output = StepOutput::new(&step, "PACKAGE_NAME");
+ (step, output)
+ }
+
+ fn winget_releaser(package_name: &StepOutput) -> Step<Use> {
+ named::uses(
+ "vedantmgoyal9",
+ "winget-releaser",
+ "19e706d4c9121098010096f9c495a70a7518b30f", // v2
+ )
+ .add_with(("identifier", package_name.to_string()))
+ .add_with(("max-versions-to-keep", 5))
+ .add_with(("token", vars::WINGET_TOKEN))
+ }
+
+ let (set_package_name, package_name) = set_package_name();
+
+ named::job(
+ Job::default()
+ .runs_on(runners::LINUX_SMALL)
+ .add_step(set_package_name)
+ .add_step(winget_releaser(&package_name)),
+ )
+}
@@ -36,6 +36,9 @@ secret!(ZED_SENTRY_MINIDUMP_ENDPOINT);
secret!(SLACK_APP_ZED_UNIT_EVALS_BOT_TOKEN);
secret!(ZED_ZIPPY_APP_ID);
secret!(ZED_ZIPPY_APP_PRIVATE_KEY);
+secret!(DISCORD_WEBHOOK_RELEASE_NOTES);
+secret!(WINGET_TOKEN);
+secret!(RELEASE_NOTES_API_TOKEN);
// todo(ci) make these secrets too...
var!(AZURE_SIGNING_ACCOUNT_NAME);
@@ -136,6 +139,15 @@ impl StepOutput {
}
}
+impl serde::Serialize for StepOutput {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ serializer.serialize_str(&self.to_string())
+ }
+}
+
impl std::fmt::Display for StepOutput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "${{{{ steps.{}.outputs.{} }}}}", self.step_id, self.name)
@@ -173,6 +185,15 @@ impl std::fmt::Display for Input {
}
}
+impl serde::Serialize for Input {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ serializer.serialize_str(&self.to_string())
+ }
+}
+
pub mod assets {
// NOTE: these asset names also exist in the zed.dev codebase.
pub const MAC_AARCH64: &str = "Zed-aarch64.dmg";