summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhar7an <99636919+har7an@users.noreply.github.com>2023-03-06 18:16:21 +0000
committerGitHub <noreply@github.com>2023-03-06 18:16:21 +0000
commit46b9bc755e419236cea2b592c834782c90c76915 (patch)
tree9cfc83a3aea680aa833089e9e427f9a8e47fdaf5
parent364f0e7c44921c23eef69c0f2d5fa4ff31aeb336 (diff)
Feature: simulate publishing (#2194)
* xtask: Add arguments to `publish` that allow specifying a custom git remote to push to and a custom cargo registry to publish packages to. * xtask/publish: Don't release `xtask` subcrate because it's not meant to be released at all. * xtask/publish: Add status messages to publish so we see what crate is currently being published, too. * xtask/publish: Disable default features on `zellij` because otherwise it tries to pick up the debug builds of the plugins, which aren't part of released version of `zellij utils`. * xtask/publish: Fix handling of custom registry * docs: Add `RELEASE.md` which explains how to simulate a zellij release. * xtask: Apply rustfmt * xtask: Remove `wasm-opt` from build steps because recent versions cause havoc in the release process in GitHub pipelines and it's primary goal is to only reduce binary size. Current rust versions seem to produce very compact wasm binaries themselves, though. * .github: Don't install wasm-opt in workflows
-rw-r--r--.github/workflows/e2e.yml2
-rw-r--r--.github/workflows/release.yml8
-rw-r--r--CONTRIBUTING.md3
-rw-r--r--docs/RELEASE.md144
-rw-r--r--xtask/src/build.rs82
-rw-r--r--xtask/src/flags.rs7
-rw-r--r--xtask/src/main.rs30
-rw-r--r--xtask/src/pipelines.rs50
8 files changed, 193 insertions, 133 deletions
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 44fd6d5cb..43f6d4a88 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -36,8 +36,6 @@ jobs:
run: sudo apt-get install -y --no-install-recommends musl-tools
- name: Add musl target
run: rustup target add x86_64-unknown-linux-musl
- - name: Install wasm-opt
- run: sudo apt-get install -y --no-install-recommends binaryen
#run: cargo install --debug cargo-make
- name: Build asset
run: cargo xtask ci e2e --build
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a47054675..315968f62 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -63,14 +63,6 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: sudo apt-get install -y --no-install-recommends musl-tools
- - name: Install wasm-opt (macos)
- if: runner.os == 'macos'
- run: brew install binaryen
-
- - name: Install wasm-opt (ubuntu)
- if: matrix.os == 'ubuntu-latest'
- run: sudo apt-get install -y --no-install-recommends binaryen
-
# Workaround for <https://github.com/actions/virtual-environments/issues/2557>
- name: Switch Xcode SDK
if: runner.os == 'macos'
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 65d528497..3543a4380 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -43,9 +43,6 @@ cargo xtask manpage
You can see a list of all commands (with supported arguments) with `cargo xtask
--help`. For convenience, `xtask` may be shortened to `x`: `cargo x build` etc.
-To run `install` or `publish`, you'll need the package `binaryen` in the
-version `wasm-opt --version` > 97, for it's command `wasm-opt`.
-
To run `test`, you will need the package `pkg-config` and a version of `openssl`.
## Running the end-to-end tests
diff --git a/docs/RELEASE.md b/docs/RELEASE.md
new file mode 100644
index 000000000..d38e47413
--- /dev/null
+++ b/docs/RELEASE.md
@@ -0,0 +1,144 @@
+# How to release a zellij version
+
+This document is primarily target at zellij maintainers in need to (prepare to)
+release a new zellij version.
+
+
+## Simulating a release
+
+This section explains how to do a "dry-run" of the release process. This is
+useful to check if a release is successful beforehand, i.e. before publishing
+it to the world. Because there is no "undo"-button for a real release as
+described below, it is recommended to perform a simulated release first.
+
+
+### Requirements
+
+You only need a publicly accessible Git repository to provide a cargo registry.
+
+
+### High-level concept
+
+The setup explained below will host a third-party cargo registry software
+([ktra](https://github.com/moriturus/ktra)) locally on your PC. In order for
+`cargo` to pick this up and be able to work with it, we must perform a few
+modifications to the zellij repository and other components. Once setup, we
+release a zellij version to this private registry and install zellij from there
+to make sure it works as expected.
+
+
+### Step-by-step guide
+
+1. Create a cargo index repository
+ 1. Create a new repo on some git forge (GitHub/GitLab/...)
+ 1. Clone the repo **with HTTPS (not SSH)**, we'll refer to the `https://`
+ clone-url as `$INDEX_REPO` for the remainder of this text
+ 1. Add a file named `config.json` with the following content in the root:
+ ```json
+ {"dl":"http://localhost:8000/dl","api":"http://localhost:8000"}
+ ```
+ 1. Generate an access token for full repo access, we'll refer to this as
+ `$TOKEN` for the remained of this text
+ 1. Create and push a commit with these changes. Provide the following HTTPS
+ credentials:
+ 1. Username: Your git-forge username
+ 1. Password: `$TOKEN`
+1. Prepare the zellij repo
+ 1. `cd` into your local copy of the zellij repository
+ 1. Add a new cargo registry to `.cargo/config.toml` like this:
+ ```toml
+
+ [registries]
+ ktra = { index = "https://$INDEX_REPO" }
+ ```
+ 1. Modify **all** `Cargo.toml` in the zellij repo to retrieve the individual
+ zellij subcrates from the private registry:
+ 1. Find all dependencies that look like this:
+ ```toml
+ zellij-utils = { path = "../zellij-utils/", version = "XXX" }
+ ```
+ 1. Change them to look like this
+ ```toml
+ zellij-utils = { path = "../zellij-utils/", version = "XXX", registry = "ktra" }
+ ```
+ 1. This applies to all zellij subcrates, e.g. `zellij-client`,
+ `zellij-server`, ... You can ignore the plugins, because these aren't
+ released as sources.
+1. Launch your private registry
+ 1. Create the file `~/.cargo/config.toml` with the following content:
+ ```
+ [registries.ktra]
+ index = "https://$INDEX_REPO"
+ ```
+ 1. Install `ktra`, the registry server: `cargo install ktra`
+ 1. In a separate shell/pane/whatever, navigate to some folder where you
+ want to store all data for the registry
+ 1. Create a config file for `ktra` named `ktra.toml` there with the
+ following content:
+ ```toml
+ [index_config]
+ remote_url = "https://$INDEX_REPO"
+ https_username = "your-git-username"
+ https_password = "$TOKEN"
+ branch = "main" # Or whatever branch name you used
+ ```
+ 1. Launch ktra (with logging to see what happens): `RUST_LOG=debug ktra`
+ 1. Get a registry token for `ktra` (The details don't really matter, unless
+ you want to reuse this registry):
+ ```bash
+ curl -X POST -H 'Content-Type: application/json' -d '{"password":"PASSWORD"}' http://localhost:8000/ktra/api/v1/new_user/ALICE
+ ```
+ 1. Login to the registry with the token you received as reply to the
+ previous command:
+ ```bash
+ cargo login --registry ktra "KTRA_TOKEN"
+ ```
+1. **Install safety measures to prevent accidentally performing a real release**:
+ 1. In your `zellij` repo, remove all configured remotes that allow you to
+ push/publish directly to the zellij main GitHub repo. Setup a fork of
+ the main zellij repo instead and configure a remote that allows you to
+ push/publish to that. Please, this is very important.
+ 1. Comment out the entire `[registry]` section in `~/.cargo/credentials` to
+ prevent accidentally pushing a new release to `crates.io`.
+1. **Simulate a release**
+ 1. Go back to the zellij repo, type:
+ ```bash
+ cargo x publish --git-remote <YOUR_ZELLIJ_FORK> --cargo-registry ktra
+ ```
+ 1. A prompt will open with the commit message for the release commit. Just
+ save and close your editor to continue
+ 1. If all goes well, the release will be done in a few minutes and all the
+ crates are published to the private `ktra` registry!
+1. Testing the release binary
+ 1. Install zellij from the registry to some local directory like this:
+ ```bash
+ $ cargo install --registry ktra --root /tmp zellij
+ ```
+ 1. Execute the binary to see if all went well:
+ ```bash
+ $ /tmp/bin/zellij
+ ```
+1. Cleaning up
+ 1. Uncomment the `[registry]` section in `~/.cargo/config.toml`
+ 1. Restore your original git remotes for the zellij repo
+ 1. Undo your last commit:
+ ```bash
+ $ git reset --hard HEAD~1
+ ```
+ 1. Undo your last commit in the remote zellij repo:
+ ```bash
+ $ git push --force <YOUR_ZELLIJ_FORK>
+ ```
+ 1. Delete the release tag:
+ ```bash
+ $ git tag -d "vX.Y.Z"
+ ```
+ 1. Delete the release tag in the remote zellij repo
+ ```bash
+ $ git push <YOUR_ZELLIJ_FORK> --force --delete "vX.Y.Z"
+ ```
+
+You're done! :tada:
+
+
+## Releasing a new version
diff --git a/xtask/src/build.rs b/xtask/src/build.rs
index 86ca7cd23..edc0c79e6 100644
--- a/xtask/src/build.rs
+++ b/xtask/src/build.rs
@@ -3,7 +3,6 @@
//! Currently has the following functions:
//!
//! - [`build`]: Builds general cargo projects (i.e. zellij components) with `cargo build`
-//! - [`wasm_opt_plugin`]: Calls `wasm-opt` on all plugins
//! - [`manpage`]: Builds the manpage with `mandown`
use crate::flags;
use anyhow::Context;
@@ -48,91 +47,10 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> {
base_cmd = base_cmd.arg("--release");
}
base_cmd.run().with_context(err_context)?;
-
- if subcrate.contains("plugins") {
- let (_, plugin_name) = subcrate
- .rsplit_once('/')
- .context("Cannot determine plugin name from '{subcrate}'")?;
-
- if flags.release {
- // Perform wasm-opt on plugin
- wasm_opt_plugin(sh, plugin_name).with_context(err_context)?;
- }
- }
}
Ok(())
}
-/// Call `wasm-opt` on all plugins.
-///
-/// Plugins are discovered automatically by scanning the contents of `target/wasm32-wasi/release`
-/// for filenames ending with `.wasm`. For this to work the plugins must be built beforehand.
-// TODO: Should this panic if there is no plugin found? What should we do when only some plugins
-// have been built before?
-pub fn wasm_opt_plugin(sh: &Shell, plugin_name: &str) -> anyhow::Result<()> {
- let err_context = || format!("failed to run 'wasm-opt' on plugin '{plugin_name}'");
-
- let wasm_opt = wasm_opt(sh).with_context(err_context)?;
-
- let asset_dir = crate::project_root()
- .join("zellij-utils")
- .join("assets")
- .join("plugins");
- sh.create_dir(&asset_dir).with_context(err_context)?;
- let _pd = sh.push_dir(asset_dir);
-
- let plugin = PathBuf::from(
- std::env::var_os("CARGO_TARGET_DIR")
- .unwrap_or(crate::project_root().join("target").into_os_string()),
- )
- .join("wasm32-wasi")
- .join("release")
- .join(plugin_name)
- .with_extension("wasm");
-
- if !plugin.is_file() {
- return Err(anyhow::anyhow!("No plugin found at '{}'", plugin.display()))
- .with_context(err_context);
- }
- let name = match plugin.file_name().with_context(err_context)?.to_str() {
- Some(name) => name,
- None => {
- return Err(anyhow::anyhow!(
- "couldn't read filename containing invalid unicode"
- ))
- .with_context(err_context)
- },
- };
-
- // This is a plugin we want to optimize
- println!();
- let msg = format!(">> Optimizing plugin '{name}'");
- crate::status(&msg);
- println!("{}", msg);
-
- let input = plugin.as_path();
- cmd!(sh, "{wasm_opt} -O {input} -o {name}")
- .run()
- .with_context(err_context)?;
-
- Ok(())
-}
-
-/// Get the path to a `wasm-opt` executable.
-///
-/// If the executable isn't found, an error is returned instead.
-// TODO: Offer the user to install latest wasm-opt on path?
-fn wasm_opt(_sh: &Shell) -> anyhow::Result<PathBuf> {
- match which::which("wasm-opt") {
- Ok(path) => Ok(path),
- Err(e) => {
- println!("!! 'wasm-opt' wasn't found but is needed for this build step.");
- println!("!! Please install it from here: https://github.com/WebAssembly/binaryen");
- Err(e).context("couldn't find 'wasm-opt' executable")
- },
- }
-}
-
/// Build the manpage with `mandown`.
// mkdir -p ${root_dir}/assets/man
// mandown ${root_dir}/docs/MANPAGE.md 1 > ${root_dir}/assets/man/zellij.1
diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs
index 2aed0013f..4630a8938 100644
--- a/xtask/src/flags.rs
+++ b/xtask/src/flags.rs
@@ -38,6 +38,10 @@ xflags::xflags! {
cmd publish {
/// Perform a dry-run (don't push/publish anything)
optional --dry-run
+ /// Push commit to custom git remote
+ optional --git-remote remote: OsString
+ /// Publish crates to custom registry
+ optional --cargo-registry registry: OsString
}
/// Package zellij for distribution (result found in ./target/dist)
@@ -151,6 +155,8 @@ pub struct Manpage;
#[derive(Debug)]
pub struct Publish {
pub dry_run: bool,
+ pub git_remote: Option<OsString>,
+ pub cargo_registry: Option<OsString>,
}
#[derive(Debug)]
@@ -175,7 +181,6 @@ pub struct Run {
pub args: Vec<OsString>,
pub data_dir: Option<PathBuf>,
-
pub singlepass: bool,
}
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index c81717056..209caa5e7 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -5,36 +5,6 @@
//! xtask install` for installation of rust-analyzer server and client.
//!
//! This binary is integrated into the `cargo` command line by using an alias in `.cargo/config`.
-// Current default "flow":
-// - format-flow: `cargo fmt`
-// - format-toml-conditioned-flow: ??
-// - build: `cargo build`
-// - test: `cargo test`
-// - clippy: `cargo clippy --all-targets --all-features -- --deny warnings $@`
-//
-// # Install flow:
-// - build-plugins-release: `cargo build --release ...`
-// - wasm-opt-plugins: `wasm-opt ...`
-// - build-release: `cargo build --release`
-// - install-mandown: `cargo install mandown`
-// - manpage: |
-// mkdir -p ${root_dir}/assets/man
-// mandown ${root_dir}/docs/MANPAGE.md 1 > ${root_dir}/assets/man/zellij.1
-// - install: `cp target/release/zellij "$1"`
-//
-// # Release flow:
-// - workspace: cargo make --profile development -- release
-//
-// # Publish flow:
-// - update-default-config:
-// - build-plugins-release: `cargo build --release ...`
-// - wasm-opt-plugins: `wasm-opt ...`
-// - release-commit:
-// - commit-all: `git commit -aem "chore(release): v${CRATE_VERSION}"`
-// - tag-release: `git tag --annotate --message "Version ${CRATE_VERSION}"
-// "v${CRATE_VERSION}"`
-// - `git push --atomic origin main "v${CRATE_VERSION}"`
-// - publish-zellij: `cargo publish [tile, client, server, utils, tile-utils, zellij]`
mod build;
mod ci;
diff --git a/xtask/src/pipelines.rs b/xtask/src/pipelines.rs
index a615c0971..ad21bffe5 100644
--- a/xtask/src/pipelines.rs
+++ b/xtask/src/pipelines.rs
@@ -44,7 +44,6 @@ pub fn make(sh: &Shell, flags: flags::Make) -> anyhow::Result<()> {
/// Runs the following steps in sequence:
///
/// - [`build`](build::build) (release, plugins only)
-/// - [`wasm_opt_plugins`](build::wasm_opt_plugins)
/// - [`build`](build::build) (release, without plugins)
/// - [`manpage`](build::manpage)
/// - Copy the executable to [target file](flags::Install::destination)
@@ -168,12 +167,30 @@ pub fn dist(sh: &Shell, _flags: flags::Dist) -> anyhow::Result<()> {
pub fn publish(sh: &Shell, flags: flags::Publish) -> anyhow::Result<()> {
let err_context = "failed to publish zellij";
- sh.change_dir(crate::project_root());
+ // Process flags
let dry_run = if flags.dry_run {
Some("--dry-run")
} else {
None
};
+ let remote = flags.git_remote.unwrap_or("origin".into());
+ let registry = if let Some(registry) = flags.cargo_registry {
+ Some(format!(
+ "--registry={}",
+ registry
+ .into_string()
+ .map_err(|registry| anyhow::Error::msg(format!(
+ "failed to convert '{:?}' to valid registry name",
+ registry
+ )))
+ .context(err_context)?
+ ))
+ } else {
+ None
+ };
+ let registry = registry.as_ref();
+
+ sh.change_dir(crate::project_root());
let cargo = crate::cargo().context(err_context)?;
let project_dir = crate::project_root();
let manifest = sh
@@ -265,22 +282,36 @@ pub fn publish(sh: &Shell, flags: flags::Publish) -> anyhow::Result<()> {
if flags.dry_run {
println!("Skipping push due to dry-run");
} else {
- cmd!(sh, "git push --atomic origin main v{version}")
+ cmd!(sh, "git push --atomic {remote} main v{version}")
.run()
.context(err_context)?;
}
// Publish all the crates
for member in crate::WORKSPACE_MEMBERS.iter() {
- if member.contains("plugin") {
+ if member.contains("plugin") || member.contains("xtask") {
continue;
}
let _pd = sh.push_dir(project_dir.join(member));
loop {
- if let Err(err) = cmd!(sh, "{cargo} publish {dry_run...}")
- .run()
- .context(err_context)
+ let msg = format!(">> Publishing '{member}'");
+ crate::status(&msg);
+ println!("{}", msg);
+
+ let more_args = match *member {
+ // This is needed for zellij to pick up the plugins from the assets included in
+ // the released zellij-utils binary
+ "." => Some("--no-default-features"),
+ _ => None,
+ };
+
+ if let Err(err) = cmd!(
+ sh,
+ "{cargo} publish {registry...} {more_args...} {dry_run...}"
+ )
+ .run()
+ .context(err_context)
{
println!();
println!("Publishing crate '{member}' failed with error:");
@@ -325,6 +356,11 @@ pub fn publish(sh: &Shell, flags: flags::Publish) -> anyhow::Result<()> {
}
}
}
+
+ println!();
+ println!(" +-----------------------------------------------+");
+ println!(" | PRAISE THE DEVS, WE HAVE A NEW ZELLIJ RELEASE |");
+ println!(" +-----------------------------------------------+");
Ok(())
};