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

new: Add download/unpack extensions. #1

Merged
merged 12 commits into from
Jan 24, 2024
Merged
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
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: moonrepo
53 changes: 53 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CI

on:
push:
branches:
- master
pull_request:

jobs:
format:
name: Format
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: moonrepo/setup-rust@v1
with:
cache: false
components: rustfmt
- run: cargo fmt --all --check
lint:
name: Lint
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: moonrepo/setup-rust@v1
with:
cache: false
components: clippy
- run: cargo clippy --workspace --all-targets
test:
name: Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: moonrepo/setup-rust@v1
with:
bins: cargo-nextest
cache: false
- uses: moonrepo/setup-toolchain@v0
- uses: moonrepo/build-wasm-plugin@v0
- run: cargo nextest run --no-default-features
31 changes: 31 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Release

permissions:
contents: write

on:
push:
tags:
- "[a-z0-9_]+-v[0-9]+*"
pull_request:

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: moonrepo/setup-rust@v1
with:
cache: false
- id: build
uses: moonrepo/build-wasm-plugin@v0
- if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
uses: ncipollo/release-action@v1
with:
artifacts: builds/*
artifactErrorsFailBuild: true
body: ${{ steps.build.outputs.changelog-entry }}
makeLatest: true
prerelease: ${{ contains(github.ref_name, '-alpha') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-rc') }}
skipIfReleaseExists: true
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,14 @@ resolver = "2"
members = ["crates/*"]

[workspace.dependencies]
moon_pdk = { path = "../moon/nextgen/pdk" }
extism-pdk = "1.0.0"
moon_pdk = "0.0.1"
moon_pdk_test_utils = "0.0.1"
starbase_sandbox = "0.1.13"

[profile.release]
codegen-units = 1
debug = false
lto = true
opt-level = "s"
panic = "abort"
3 changes: 2 additions & 1 deletion crates/dlu/Cargo.toml → crates/common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[package]
name = "moon_extension_dlu"
name = "moon_extension_common"
version = "0.1.0"
edition = "2021"
license = "MIT"
publish = false

[dependencies]
Expand Down
30 changes: 30 additions & 0 deletions crates/common/src/download.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use extism_pdk::debug;
use moon_pdk::{fetch_url_bytes, AnyResult, VirtualPath};
use std::fs;

pub fn download_from_url<U: AsRef<str>, P: AsRef<VirtualPath>>(
src_url: U,
dst_dir: P,
file_name: Option<&str>,
) -> AnyResult<VirtualPath> {
let url = src_url.as_ref();
let dir = dst_dir.as_ref();

debug!("Downloading file from <url>{}</url>", url);

// Extract the file name from the URL
let file_name = file_name.unwrap_or_else(|| &url[url.rfind('/').unwrap() + 1..]);

// Fetch the bytes of the URL
let bytes = fetch_url_bytes(url)?;

// Write the to the provided file
let file = dir.join(file_name);

fs::create_dir_all(dir)?;
fs::write(&file, bytes)?;

debug!("Downloaded to <path>{}</path>", file.real_path().display());

Ok(file)
}
1 change: 1 addition & 0 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod download;
2 changes: 0 additions & 2 deletions crates/dlu/src/lib.rs

This file was deleted.

5 changes: 5 additions & 0 deletions crates/download/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## 0.1.0

#### 🚀 Updates

- Initial release!
22 changes: 22 additions & 0 deletions crates/download/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "moon_extension_download"
version = "0.0.1"
edition = "2021"
license = "MIT"
publish = false

[lib]
crate-type = ['cdylib']

[dependencies]
moon_extension_common = { path = "../common" }
extism-pdk = { workspace = true }
moon_pdk = { workspace = true }

[dev-dependencies]
moon_pdk_test_utils = { workspace = true }
starbase_sandbox = { workspace = true }

[features]
default = ["wasm"]
wasm = []
68 changes: 68 additions & 0 deletions crates/download/src/download_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use extism_pdk::*;
use moon_extension_common::download::download_from_url;
use moon_pdk::{
anyhow, args::*, extension::*, host_log, plugin_err, virtual_path, HostLogInput, HostLogTarget,
VirtualPath,
};

#[host_fn]
extern "ExtismHost" {
fn host_log(input: Json<HostLogInput>);
fn to_virtual_path(path: String) -> String;
}

#[derive(Args)]
pub struct DownloadExtensionArgs {
#[arg(long, short = 'u', required = true)]
pub url: String,

#[arg(long, short = 'd')]
pub dest: Option<String>,

#[arg(long)]
pub name: Option<String>,
}

#[plugin_fn]
pub fn execute_extension(Json(input): Json<ExecuteExtensionInput>) -> FnResult<()> {
let args = parse_args::<DownloadExtensionArgs>(&input.args)?;

if !args.url.starts_with("http") {
return Err(plugin_err!("A valid URL is required for downloading."));
}

// Determine destination directory
debug!("Determining destination directory");

let dest_dir = virtual_path!(
buf,
input
.context
.get_absolute_path(args.dest.as_deref().unwrap_or_default())
);

if dest_dir.exists() && dest_dir.is_file() {
return Err(plugin_err!(
"Destination <path>{}</path> must be a directory, found a file.",
dest_dir.real_path().display(),
));
}

debug!(
"Destination <path>{}</path> will be used",
dest_dir.real_path().display(),
);

// Attempt to download the file
host_log!(stdout, "Downloading <url>{}</url>", args.url);

let dest_file = download_from_url(&args.url, &dest_dir, args.name.as_deref())?;

host_log!(
stdout,
"Downloaded to <path>{}</path>",
dest_file.real_path().display()
);

Ok(())
}
5 changes: 5 additions & 0 deletions crates/download/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[cfg(feature = "wasm")]
mod download_ext;

#[cfg(feature = "wasm")]
pub use download_ext::*;
109 changes: 109 additions & 0 deletions crates/download/tests/download_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use moon_pdk_test_utils::{create_extension, ExecuteExtensionInput};
use starbase_sandbox::create_empty_sandbox;
use std::fs;

mod download {
use super::*;

#[test]
#[should_panic(expected = "the following required arguments were not provided")]
fn errors_if_no_args() {
let sandbox = create_empty_sandbox();
let plugin = create_extension("test", sandbox.path());

plugin.execute_extension(ExecuteExtensionInput {
args: vec![],
context: plugin.create_context(sandbox.path()),
});
}

#[test]
#[should_panic(expected = "A valid URL is required for downloading.")]
fn errors_if_not_a_url() {
let sandbox = create_empty_sandbox();
let plugin = create_extension("test", sandbox.path());

plugin.execute_extension(ExecuteExtensionInput {
args: vec!["--url".into(), "invalid".into()],
context: plugin.create_context(sandbox.path()),
});
}

#[test]
#[should_panic(expected = "must be a directory, found a file")]
fn errors_if_dest_is_a_file() {
let sandbox = create_empty_sandbox();
let plugin = create_extension("test", sandbox.path());

sandbox.create_file("dest", "file");

plugin.execute_extension(ExecuteExtensionInput {
args: vec![
"--url".into(),
"https://raw.githubusercontent.com/moonrepo/moon/master/README.md".into(),
"--dest".into(),
"./dest".into(),
],
context: plugin.create_context(sandbox.path()),
});
}

#[test]
fn downloads_file() {
let sandbox = create_empty_sandbox();
let plugin = create_extension("test", sandbox.path());

plugin.execute_extension(ExecuteExtensionInput {
args: vec![
"--url".into(),
"https://raw.githubusercontent.com/moonrepo/moon/master/README.md".into(),
"--dest".into(),
".".into(),
],
context: plugin.create_context(sandbox.path()),
});

let file = sandbox.path().join("README.md");

assert!(file.exists());
assert_eq!(fs::metadata(file).unwrap().len(), 4013);
}

#[test]
fn downloads_file_to_subdir() {
let sandbox = create_empty_sandbox();
let plugin = create_extension("test", sandbox.path());

plugin.execute_extension(ExecuteExtensionInput {
args: vec![
"--url".into(),
"https://raw.githubusercontent.com/moonrepo/moon/master/README.md".into(),
"--dest".into(),
"./sub/dir".into(),
],
context: plugin.create_context(sandbox.path()),
});

assert!(sandbox.path().join("sub/dir/README.md").exists());
}

#[test]
fn downloads_file_with_custom_name() {
let sandbox = create_empty_sandbox();
let plugin = create_extension("test", sandbox.path());

plugin.execute_extension(ExecuteExtensionInput {
args: vec![
"--url".into(),
"https://raw.githubusercontent.com/moonrepo/moon/master/README.md".into(),
"--dest".into(),
"./sub/dir".into(),
"--name".into(),
"moon.md".into(),
],
context: plugin.create_context(sandbox.path()),
});

assert!(sandbox.path().join("sub/dir/moon.md").exists());
}
}
5 changes: 5 additions & 0 deletions crates/unpack/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## 0.1.0

#### 🚀 Updates

- Initial release!
26 changes: 26 additions & 0 deletions crates/unpack/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "moon_extension_unpack"
version = "0.0.1"
edition = "2021"
license = "MIT"
publish = false

[lib]
crate-type = ['cdylib']

[dependencies]
moon_extension_common = { path = "../common" }
extism-pdk = { workspace = true }
moon_pdk = { workspace = true }
starbase_archive = { version = "0.2.5", default-features = false, features = [
"tar-gz",
"zip",
] }

[dev-dependencies]
moon_pdk_test_utils = { workspace = true }
starbase_sandbox = { workspace = true }

[features]
default = ["wasm"]
wasm = []
Loading