Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Snap Package Support #6532

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions core/tauri-config-schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,13 @@
"appimage"
]
},
{
"description": "The Snap bundle (.snap).",
"type": "string",
"enum": [
"snap"
]
},
{
"description": "The Microsoft Installer bundle (.msi).",
"type": "string",
Expand Down
3 changes: 3 additions & 0 deletions core/tauri-utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ pub enum BundleType {
Deb,
/// The AppImage bundle (.appimage).
AppImage,
/// The Snap bundle (.snap).
Snap,
/// The Microsoft Installer bundle (.msi).
Msi,
/// The NSIS bundle (.exe).
Expand All @@ -100,6 +102,7 @@ impl Display for BundleType {
match self {
Self::Deb => "deb",
Self::AppImage => "appimage",
Self::Snap => "snap",
Self::Msi => "msi",
Self::Nsis => "nsis",
Self::App => "app",
Expand Down
2 changes: 2 additions & 0 deletions tooling/bundler/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ pub fn bundle_project(settings: Settings) -> crate::Result<Vec<Bundle>> {
PackageType::Rpm => linux::rpm::bundle_project(&settings)?,
#[cfg(target_os = "linux")]
PackageType::AppImage => linux::appimage::bundle_project(&settings)?,
#[cfg(target_os = "linux")]
PackageType::Snap => linux::snap::bundle_project(&settings)?,

// updater is dependant of multiple bundle, we send our bundles to prevent rebuilding
PackageType::Updater => {
Expand Down
1 change: 1 addition & 0 deletions tooling/bundler/src/bundle/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
pub mod appimage;
pub mod debian;
pub mod rpm;
pub mod snap;
77 changes: 77 additions & 0 deletions tooling/bundler/src/bundle/linux/snap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2016-2019 Cargo-Bundle developers <https://github.com/burtonageo/cargo-bundle>
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use handlebars::Handlebars;
use log::info;

use crate::Settings;

use std::{path::PathBuf, path::Path, process::Command, collections::BTreeMap, fs::{write, self}};

/// Bundles the project with snapcraft
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
let release_folder = settings.project_out_directory();
let target_folder = release_folder.clone().parent().expect("Unable to find target folder in your project");
let snap_folder = target_folder.clone().join("snap");
info!("Generating yaml files to target/snap folder...");
generate_yaml(&settings, &snap_folder).expect("Failed to generate yaml files.");
//check for snapcraft on system
check_snapcraft().expect("Snaft cannot be found on your system. Please install Snapcraft");
info!("Running 'snapcraft' bundler...");
let snapcraft_output = run_snapcraft(&target_folder).expect("Error running Snapcraft").wait();
info!("✅ Successfully bundled snap package in target folder!");
let snap_file = fs::read_dir(&target_folder)
.expect("Unable to read target folder")
.filter_map(|entry| entry.ok())
.filter(|entry| entry.path().extension().unwrap_or_default() == "snap")
.max_by_key(|entry| entry.metadata().expect("Unable to get metadata").modified()
.expect("Unable to get modified date"))
.expect("Unable to find snap file in target folder")
.path();
Ok(vec![snap_file])
}

fn generate_yaml(settings: &Settings, snap_folder: &PathBuf) -> crate::Result<()> {
let mut sh_map = BTreeMap::new();
sh_map.insert("package-name", settings.main_binary_name());
sh_map.insert("package-summary", settings.short_description());
if let Some(long_description) = settings.long_description() {
sh_map.insert("package-description", long_description);
}
else {
sh_map.insert("package-description", settings.short_description());
}
sh_map.insert("app-name", settings.main_binary_name());
sh_map.insert("version", settings.version_string());
let mut handlebars = Handlebars::new();
handlebars
.register_template_string("snapcraft", include_str!("templates/snapcore22"))
.expect("Failed to register template for handlebars");
let temp = handlebars.render("snapcraft", &sh_map)?;

// create the yaml file in snap/ folder.
fs::create_dir_all(&snap_folder)?;
let sh_file = snap_folder.join("snapcraft.yaml");
write(&sh_file, temp)?;
return Ok(());
}


//Checks if the user has snapcraft installed or not
fn check_snapcraft() -> Result<std::process::Output, std::io::Error> {
let output = Command::new("snapcraft")
.arg("--version")
.output();
output
}

fn run_snapcraft(target_folder: &Path) -> Result<std::process::Child, std::io::Error> {
let output = Command::new("/bin/sh")
.current_dir(&target_folder)
.arg("-c")
.arg("snapcraft")
.spawn();
output
}
30 changes: 30 additions & 0 deletions tooling/bundler/src/bundle/linux/templates/snapcore22
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: {{package-name}}
base: core22
version: {{version}}
summary: {{package-summary}}
description: {{package-description}}
grade: devel
confinement: strict
apps:
{{app-name}}:
command: {{app-name}}
extensions:
- gnome
desktop: {{app-name}}.desktop
parts:
dump-binary:
plugin: dump
source: release
source-type: local
stage:
- lib
- icons
- {{app-name}}
- {{app-name}}.desktop
prime:
- lib
- icons
- {{app-name}}
- {{app-name}}.desktop
stage-packages:
- libc6
8 changes: 7 additions & 1 deletion tooling/bundler/src/bundle/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub enum PackageType {
Deb,
/// The Linux RPM bundle (.rpm).
Rpm,
// The Linux Snap Bundle (.snap).
Snap,
/// The Linux AppImage bundle (.AppImage).
AppImage,
/// The macOS DMG bundle (.dmg).
Expand All @@ -45,6 +47,7 @@ impl From<BundleType> for PackageType {
match bundle {
BundleType::Deb => Self::Deb,
BundleType::AppImage => Self::AppImage,
BundleType::Snap => Self::Snap,
BundleType::Msi => Self::WindowsMsi,
BundleType::Nsis => Self::Nsis,
BundleType::App => Self::MacOsBundle,
Expand All @@ -67,6 +70,7 @@ impl PackageType {
"app" => Some(PackageType::MacOsBundle),
"rpm" => Some(PackageType::Rpm),
"appimage" => Some(PackageType::AppImage),
"snap" => Some(PackageType::Snap),
"dmg" => Some(PackageType::Dmg),
"updater" => Some(PackageType::Updater),
_ => None,
Expand All @@ -84,6 +88,7 @@ impl PackageType {
PackageType::MacOsBundle => "app",
PackageType::Rpm => "rpm",
PackageType::AppImage => "appimage",
PackageType::Snap => "snap",
PackageType::Dmg => "dmg",
PackageType::Updater => "updater",
}
Expand Down Expand Up @@ -112,6 +117,7 @@ const ALL_PACKAGE_TYPES: &[PackageType] = &[
PackageType::Dmg,
#[cfg(target_os = "linux")]
PackageType::AppImage,
PackageType::Snap,
PackageType::Updater,
];

Expand Down Expand Up @@ -651,7 +657,7 @@ impl Settings {
let mut platform_types = match target_os.as_str() {
"macos" => vec![PackageType::MacOsBundle, PackageType::Dmg],
"ios" => vec![PackageType::IosBundle],
"linux" => vec![PackageType::Deb, PackageType::AppImage],
"linux" => vec![PackageType::Deb, PackageType::AppImage, PackageType::Snap],
"windows" => vec![PackageType::WindowsMsi, PackageType::Nsis],
os => {
return Err(crate::Error::GenericError(format!(
Expand Down
Loading