mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-11-14 20:56:49 +00:00
ci: Create xtask and workflow for release automation
This commit is contained in:
8 files changed
+215
-17
No files matched your search
+7
-2
@@ -9,13 +9,18 @@ readme.workspace = true
|
||||
repository.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["generate-docs"]
|
||||
generate-docs = ["dep:conduwuit", "dep:conduwuit-admin"]
|
||||
|
||||
[dependencies]
|
||||
conduwuit-admin.workspace = true
|
||||
conduwuit.workspace = true
|
||||
clap.workspace = true
|
||||
conduwuit = { workspace = true, optional = true }
|
||||
conduwuit-admin = { workspace = true, optional = true }
|
||||
|
||||
askama = "0.15.1"
|
||||
cargo_metadata = "0.23.1"
|
||||
duct = "1.1.1"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
+7
-1
@@ -1,5 +1,6 @@
|
||||
mod tasks;
|
||||
|
||||
use cargo_metadata::MetadataCommand;
|
||||
use clap::Parser;
|
||||
|
||||
use crate::tasks::Task;
|
||||
@@ -22,5 +23,10 @@ struct Args {
|
||||
fn main() -> impl std::process::Termination {
|
||||
let BaseArgs { task, args } = BaseArgs::parse();
|
||||
|
||||
task.invoke(args)
|
||||
let metadata = MetadataCommand::new()
|
||||
.no_deps()
|
||||
.exec()
|
||||
.expect("should have been able to run cargo");
|
||||
|
||||
task.invoke(metadata, args)
|
||||
}
|
||||
@@ -2,8 +2,6 @@ mod admin_commands;
|
||||
|
||||
use std::{collections::HashMap, fs::File, io::Write, path::{Path, PathBuf}};
|
||||
|
||||
use cargo_metadata::MetadataCommand;
|
||||
|
||||
use crate::tasks::TaskResult;
|
||||
|
||||
trait FileOutput {
|
||||
@@ -68,14 +66,9 @@ pub(crate) struct Args {
|
||||
}
|
||||
|
||||
#[expect(clippy::needless_pass_by_value)]
|
||||
pub(super) fn run(common_args: crate::Args, task_args: Args) -> TaskResult<()> {
|
||||
pub(super) fn run(metadata: cargo_metadata::Metadata, common_args: crate::Args, task_args: Args) -> TaskResult<()> {
|
||||
let mut queue = FileQueue::default();
|
||||
|
||||
let metadata = MetadataCommand::new()
|
||||
.no_deps()
|
||||
.exec()
|
||||
.expect("should have been able to run cargo");
|
||||
|
||||
let root = task_args.root.unwrap_or_else(|| metadata.workspace_root.join_os("docs/"));
|
||||
|
||||
admin_commands::generate(&mut queue)?;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
use askama::Template;
|
||||
use duct::cmd;
|
||||
|
||||
use crate::tasks::TaskResult;
|
||||
|
||||
#[derive(askama::Template)]
|
||||
#[template(path = "release-notes.md")]
|
||||
struct ReleaseNotes<'a> {
|
||||
version: &'a str,
|
||||
header: &'a str,
|
||||
changelog: &'a str,
|
||||
}
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args;
|
||||
|
||||
pub(super) fn run(_: cargo_metadata::Metadata, _: crate::Args, _: Args) -> TaskResult<()> {
|
||||
const TAG_PREFIX: &str = "v";
|
||||
|
||||
let tag = cmd!("git", "describe", "--exact")
|
||||
.stdout_capture()
|
||||
.read()
|
||||
.expect("failed to get current tag");
|
||||
|
||||
let version = tag
|
||||
.strip_prefix(TAG_PREFIX)
|
||||
.expect("tag did not start with expected prefix");
|
||||
|
||||
eprintln!("Generating release notes for {version}");
|
||||
|
||||
let header = cmd!("git", "tag", "-l", &tag, "--format", "%(contents)")
|
||||
.stdout_capture()
|
||||
.read()
|
||||
.expect("failed to read tag contents");
|
||||
|
||||
let mut changelog = cmd!("towncrier", "build", "--draft", "--version", &version)
|
||||
.stdout_capture()
|
||||
.stderr_null()
|
||||
.read()
|
||||
.expect("failed to run towncrier");
|
||||
|
||||
|
||||
// towncrier generates a title with the project name and date, which we don't want. remove it here.
|
||||
// split off the first line and make sure it's a markdown heading
|
||||
assert!(changelog.starts_with("# "), "expected h1 at the start of towncrier output");
|
||||
let changelog = changelog.split_off(changelog.find("\n\n").unwrap());
|
||||
|
||||
let rendered = ReleaseNotes {
|
||||
version,
|
||||
header: header.trim(),
|
||||
changelog: changelog.trim()
|
||||
}.render()?;
|
||||
|
||||
println!("{rendered}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+12
-6
@@ -1,29 +1,33 @@
|
||||
type TaskResult<T> = Result<T, Box<dyn std::error::Error>>;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! tasks {
|
||||
(
|
||||
$(
|
||||
$module:ident: $desc:literal
|
||||
$(#[$meta:meta])? $module:ident: $desc:literal
|
||||
),*
|
||||
) => {
|
||||
$(pub(super) mod $module;)*
|
||||
$(
|
||||
$(#[cfg($meta)])?
|
||||
pub(super) mod $module;
|
||||
)*
|
||||
|
||||
#[derive(clap::Subcommand)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub(super) enum Task {
|
||||
$(
|
||||
$(#[cfg($meta)])?
|
||||
#[clap(about = $desc, long_about = None)]
|
||||
$module($module::Args),
|
||||
)*
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub(super) fn invoke(self, common_args: $crate::Args) -> TaskResult<impl std::process::Termination> {
|
||||
pub(super) fn invoke(self, metadata: cargo_metadata::Metadata, common_args: $crate::Args) -> TaskResult<impl std::process::Termination> {
|
||||
match self {
|
||||
$(
|
||||
$(#[cfg($meta)])?
|
||||
Self::$module(task_args) => {
|
||||
$module::run(common_args, task_args)
|
||||
$module::run(metadata, common_args, task_args)
|
||||
},
|
||||
)*
|
||||
}
|
||||
@@ -33,5 +37,7 @@ macro_rules! tasks {
|
||||
}
|
||||
|
||||
tasks! {
|
||||
generate_docs: "Generate various documentation files. This is run automatically when compiling the website."
|
||||
#[feature = "generate-docs"]
|
||||
generate_docs: "Generate various documentation files. This is run automatically when compiling the website.",
|
||||
generate_release_notes: "Generate release notes from towncrier and a git tag. Used by CI."
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# Continuwuity {{ version }}
|
||||
|
||||
{{ header }}
|
||||
|
||||
{{ changelog }}
|
||||
|
||||
---
|
||||
|
||||
## Get Continuwuity
|
||||
|
||||
### Docker Images
|
||||
- Forgejo: `forgejo.ellis.link/continuwuation/continuwuity:v{{ version }}`
|
||||
|
||||
Mirrors (may be outdated):
|
||||
- Docker Hub: `docker.io/continuwuity/continuwuity:v{{ version }}`
|
||||
- GitHub: `ghcr.io/continuwuity/continuwuity:v{{ version }}`
|
||||
- GitLab: `registry.gitlab.com/continuwuity/continuwuity:v{{ version }}`
|
||||
|
||||
You can also use the `latest` tag for the most recent release.
|
||||
|
||||
### First-party Packages
|
||||
|
||||
- [Debian packages](https://forgejo.ellis.link/continuwuation/-/packages/debian/continuwuity/)
|
||||
- [Fedora RPM packages](https://forgejo.ellis.link/continuwuation/-/packages/rpm/continuwuity/)
|
||||
|
||||
### Community Packages
|
||||
|
||||
[](https://repology.org/project/continuwuity/versions)
|
||||
|
||||
### Binaries
|
||||
|
||||
Plain binaries are distributed below. They require glibc and liburing to work - most distributions already have these installed.
|
||||
|
||||
### From Source
|
||||
See our [deployment documentation](https://continuwuity.org/deploying.html) for instructions on building from source.
|
||||
Reference in new issue
Block a user