From fa275731bec4fdc2f9dfaee0950ebcf3870d5799 Mon Sep 17 00:00:00 2001 From: Jacob Bolda Date: Tue, 23 Jul 2024 21:20:42 -0500 Subject: [PATCH 1/3] (chore) covector comment on forks (#1566) --- .../workflows/covector-comment-on-fork.yml | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/covector-comment-on-fork.yml diff --git a/.github/workflows/covector-comment-on-fork.yml b/.github/workflows/covector-comment-on-fork.yml new file mode 100644 index 000000000..69c85857b --- /dev/null +++ b/.github/workflows/covector-comment-on-fork.yml @@ -0,0 +1,30 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT + +name: covector comment +on: + workflow_run: + workflows: [covector status] # the `name` of the workflow run on `pull_request` running `status` with `comment: true` + types: + - completed + +# note all other permissions are set to none if not specified +# and these set the permissions for `secrets.GITHUB_TOKEN` +permissions: + # to read the action artifacts on `covector status` workflows + actions: read + # to write the comment + pull-requests: write + +jobs: + download: + runs-on: ubuntu-latest + if: github.event.workflow_run.conclusion == 'success' && + (github.event.workflow_run.head_repository.full_name != github.repository || github.actor == 'dependabot[bot]') + steps: + - name: covector status + uses: jbolda/covector/packages/action@covector-v0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + command: "status" From 20a1d24ee004e77c2d12a0e20d258ce120216ed1 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Tue, 23 Jul 2024 23:32:21 -0300 Subject: [PATCH 2/3] feat(log): add Builder::split to get the raw logger implementation (#1579) * feat(log): add Builder::split to get the raw logger implementation This function lets you split the Builder to return the raw logger implementation along the TauriPlugin to be registered. Useful to pipe the logger to other implementations such as multi_log or tauri-plugin-devtools, allowing the plugin to be used along other logging systems. * clippy * covector --- .changes/log-split.md | 5 + Cargo.lock | 9 +- plugins/log/Cargo.toml | 1 + plugins/log/src/lib.rs | 235 ++++++++++++++++++++++++++--------------- 4 files changed, 158 insertions(+), 92 deletions(-) create mode 100644 .changes/log-split.md diff --git a/.changes/log-split.md b/.changes/log-split.md new file mode 100644 index 000000000..9b9a9e48f --- /dev/null +++ b/.changes/log-split.md @@ -0,0 +1,5 @@ +--- +"log-plugin": patch +--- + +Added `Builder::split` which returns the raw logger implementation so you can pipe to other loggers such as `multi_log` or `tauri-plugin-devtools`. diff --git a/Cargo.lock b/Cargo.lock index a5c532b36..74622341f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -200,7 +200,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "api" -version = "2.0.0-beta.13" +version = "2.0.0-beta.14" dependencies = [ "log", "serde", @@ -6603,6 +6603,7 @@ dependencies = [ "swift-rs", "tauri", "tauri-plugin", + "thiserror", "time", ] @@ -6621,7 +6622,7 @@ dependencies = [ [[package]] name = "tauri-plugin-notification" -version = "2.0.0-beta.10" +version = "2.0.0-beta.11" dependencies = [ "color-backtrace", "ctor", @@ -6727,7 +6728,7 @@ dependencies = [ [[package]] name = "tauri-plugin-sql" -version = "2.0.0-beta.9" +version = "2.0.0-beta.10" dependencies = [ "futures-core", "indexmap 2.2.6", @@ -6778,7 +6779,7 @@ dependencies = [ [[package]] name = "tauri-plugin-updater" -version = "2.0.0-beta.10" +version = "2.0.0-beta.11" dependencies = [ "base64 0.22.1", "dirs 5.0.1", diff --git a/plugins/log/Cargo.toml b/plugins/log/Cargo.toml index 6b975548e..c62e5f259 100644 --- a/plugins/log/Cargo.toml +++ b/plugins/log/Cargo.toml @@ -25,6 +25,7 @@ byte-unit = "5" log = { workspace = true, features = [ "kv_unstable" ] } time = { version = "0.3", features = [ "formatting", "local-offset" ] } fern = "0.6" +thiserror = "1" [target."cfg(target_os = \"android\")".dependencies] android_logger = "0.14" diff --git a/plugins/log/src/lib.rs b/plugins/log/src/lib.rs index b9eb4baae..2691c55fe 100644 --- a/plugins/log/src/lib.rs +++ b/plugins/log/src/lib.rs @@ -24,11 +24,11 @@ use std::{ iter::FromIterator, path::{Path, PathBuf}, }; -use tauri::Emitter; use tauri::{ plugin::{self, TauriPlugin}, Manager, Runtime, }; +use tauri::{AppHandle, Emitter}; pub use fern; use time::OffsetDateTime; @@ -75,6 +75,18 @@ const DEFAULT_LOG_TARGETS: [Target; 2] = [ Target::new(TargetKind::LogDir { file_name: None }), ]; +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error(transparent)] + Tauri(#[from] tauri::Error), + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + TimeFormat(#[from] time::error::Format), + #[error(transparent)] + InvalidFormatDescription(#[from] time::error::InvalidFormatDescription), +} + /// An enum representing the available verbosity levels of the logger. /// /// It is very similar to the [`log::Level`], but serializes to unsigned ints instead of strings. @@ -395,97 +407,134 @@ impl Builder { }) } - pub fn build(mut self) -> TauriPlugin { - plugin::Builder::new("log") - .invoke_handler(tauri::generate_handler![log]) - .setup(move |app_handle, _api| { - let app_name = &app_handle.package_info().name; + fn acquire_logger( + app_handle: &AppHandle, + mut dispatch: fern::Dispatch, + rotation_strategy: RotationStrategy, + timezone_strategy: TimezoneStrategy, + max_file_size: u128, + targets: Vec, + ) -> Result<(log::LevelFilter, Box), Error> { + let app_name = &app_handle.package_info().name; + + // setup targets + for target in targets { + let mut target_dispatch = fern::Dispatch::new(); + for filter in target.filters { + target_dispatch = target_dispatch.filter(filter); + } - // setup targets - for target in self.targets { - let mut target_dispatch = fern::Dispatch::new(); - for filter in target.filters { - target_dispatch = target_dispatch.filter(filter); + let logger = match target.kind { + #[cfg(target_os = "android")] + TargetKind::Stdout | TargetKind::Stderr => fern::Output::call(android_logger::log), + #[cfg(target_os = "ios")] + TargetKind::Stdout | TargetKind::Stderr => fern::Output::call(move |record| { + let message = format!("{}", record.args()); + unsafe { + ios::tauri_log( + match record.level() { + log::Level::Trace | log::Level::Debug => 1, + log::Level::Info => 2, + log::Level::Warn | log::Level::Error => 3, + }, + ios::NSString::new(message.as_str()).0 as _, + ); + } + }), + #[cfg(desktop)] + TargetKind::Stdout => std::io::stdout().into(), + #[cfg(desktop)] + TargetKind::Stderr => std::io::stderr().into(), + TargetKind::Folder { path, file_name } => { + if !path.exists() { + fs::create_dir_all(&path)?; } - let logger = match target.kind { - #[cfg(target_os = "android")] - TargetKind::Stdout | TargetKind::Stderr => { - fern::Output::call(android_logger::log) - } - #[cfg(target_os = "ios")] - TargetKind::Stdout | TargetKind::Stderr => { - fern::Output::call(move |record| { - let message = format!("{}", record.args()); - unsafe { - ios::tauri_log( - match record.level() { - log::Level::Trace | log::Level::Debug => 1, - log::Level::Info => 2, - log::Level::Warn | log::Level::Error => 3, - }, - ios::NSString::new(message.as_str()).0 as _, - ); - } - }) - } - #[cfg(desktop)] - TargetKind::Stdout => std::io::stdout().into(), - #[cfg(desktop)] - TargetKind::Stderr => std::io::stderr().into(), - TargetKind::Folder { path, file_name } => { - if !path.exists() { - fs::create_dir_all(&path)?; - } - - fern::log_file(get_log_file_path( - &path, - file_name.as_deref().unwrap_or(app_name), - &self.rotation_strategy, - &self.timezone_strategy, - self.max_file_size, - )?)? - .into() - } - #[cfg(mobile)] - TargetKind::LogDir { .. } => continue, - #[cfg(desktop)] - TargetKind::LogDir { file_name } => { - let path = app_handle.path().app_log_dir()?; - if !path.exists() { - fs::create_dir_all(&path)?; - } - - fern::log_file(get_log_file_path( - &path, - file_name.as_deref().unwrap_or(app_name), - &self.rotation_strategy, - &self.timezone_strategy, - self.max_file_size, - )?)? - .into() - } - TargetKind::Webview => { - let app_handle = app_handle.clone(); - - fern::Output::call(move |record| { - let payload = RecordPayload { - message: record.args().to_string(), - level: record.level().into(), - }; - let app_handle = app_handle.clone(); - tauri::async_runtime::spawn(async move { - let _ = app_handle.emit("log://log", payload); - }); - }) - } - }; - target_dispatch = target_dispatch.chain(logger); - - self.dispatch = self.dispatch.chain(target_dispatch); + fern::log_file(get_log_file_path( + &path, + file_name.as_deref().unwrap_or(app_name), + &rotation_strategy, + &timezone_strategy, + max_file_size, + )?)? + .into() } + #[cfg(mobile)] + TargetKind::LogDir { .. } => continue, + #[cfg(desktop)] + TargetKind::LogDir { file_name } => { + let path = app_handle.path().app_log_dir()?; + if !path.exists() { + fs::create_dir_all(&path)?; + } - self.dispatch.apply()?; + fern::log_file(get_log_file_path( + &path, + file_name.as_deref().unwrap_or(app_name), + &rotation_strategy, + &timezone_strategy, + max_file_size, + )?)? + .into() + } + TargetKind::Webview => { + let app_handle = app_handle.clone(); + + fern::Output::call(move |record| { + let payload = RecordPayload { + message: record.args().to_string(), + level: record.level().into(), + }; + let app_handle = app_handle.clone(); + tauri::async_runtime::spawn(async move { + let _ = app_handle.emit("log://log", payload); + }); + }) + } + }; + target_dispatch = target_dispatch.chain(logger); + + dispatch = dispatch.chain(target_dispatch); + } + + Ok(dispatch.into_log()) + } + + fn plugin_builder() -> plugin::Builder { + plugin::Builder::new("log").invoke_handler(tauri::generate_handler![log]) + } + + #[allow(clippy::type_complexity)] + pub fn split( + self, + app_handle: &AppHandle, + ) -> Result<(TauriPlugin, log::LevelFilter, Box), Error> { + let plugin = Self::plugin_builder(); + let (max_level, log) = Self::acquire_logger( + app_handle, + self.dispatch, + self.rotation_strategy, + self.timezone_strategy, + self.max_file_size, + self.targets, + )?; + + Ok((plugin.build(), max_level, log)) + } + + pub fn build(self) -> TauriPlugin { + Self::plugin_builder() + .setup(move |app_handle, _api| { + let (max_level, log) = Self::acquire_logger( + app_handle, + self.dispatch, + self.rotation_strategy, + self.timezone_strategy, + self.max_file_size, + self.targets, + )?; + + attach_logger(max_level, log)?; Ok(()) }) @@ -493,13 +542,23 @@ impl Builder { } } +/// Attaches the given logger +pub fn attach_logger( + max_level: log::LevelFilter, + log: Box, +) -> Result<(), log::SetLoggerError> { + log::set_boxed_logger(log)?; + log::set_max_level(max_level); + Ok(()) +} + fn get_log_file_path( dir: &impl AsRef, file_name: &str, rotation_strategy: &RotationStrategy, timezone_strategy: &TimezoneStrategy, max_file_size: u128, -) -> Result> { +) -> Result { let path = dir.as_ref().join(format!("{file_name}.log")); if path.exists() { From bb09c7ca6eb52d32b9ddf6530d21d39812473499 Mon Sep 17 00:00:00 2001 From: Jacob Bolda Date: Wed, 24 Jul 2024 08:40:11 -0500 Subject: [PATCH 3/3] ci: npm publish with provenance (#1582) * npm publish with provenance * update token to allow creating id-token --- .changes/config.json | 12 +++++++++++- .github/workflows/covector-version-or-publish-v2.yml | 8 ++++++++ .github/workflows/covector-version-or-publish.yml | 8 ++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.changes/config.json b/.changes/config.json index b01389c47..3e5527246 100644 --- a/.changes/config.json +++ b/.changes/config.json @@ -9,7 +9,17 @@ "url": "https://registry.npmjs.com/${ pkg.pkgFile.pkg.name }/${ pkg.pkgFile.version }" } }, - "publish": ["pnpm build", "pnpm publish --access public --no-git-checks"] + "publish": [ + { + "command": "pnpm build", + "dryRunCommand": "pnpm build" + }, + { + "command": "npm publish --provenance --access public", + "dryRunCommand": "npm publish --provenance --access public --dry-run", + "pipe": true + } + ] }, "rust": { "version": true, diff --git a/.github/workflows/covector-version-or-publish-v2.yml b/.github/workflows/covector-version-or-publish-v2.yml index 37307dee5..0662c688d 100644 --- a/.github/workflows/covector-version-or-publish-v2.yml +++ b/.github/workflows/covector-version-or-publish-v2.yml @@ -9,6 +9,14 @@ on: branches: - v2 +permissions: + # required for npm provenance + id-token: write + # required to create the GitHub Release + contents: write + # required for creating the Version Packages Release + pull-requests: write + jobs: version-or-publish: runs-on: ubuntu-latest diff --git a/.github/workflows/covector-version-or-publish.yml b/.github/workflows/covector-version-or-publish.yml index d705669a8..1828bf2f0 100644 --- a/.github/workflows/covector-version-or-publish.yml +++ b/.github/workflows/covector-version-or-publish.yml @@ -9,6 +9,14 @@ on: branches: - v1 +permissions: + # required for npm provenance + id-token: write + # required to create the GitHub Release + contents: write + # required for creating the Version Packages Release + pull-requests: write + jobs: version-or-publish: runs-on: ubuntu-latest