Skip to content
This repository has been archived by the owner on Jan 7, 2025. It is now read-only.

Commit

Permalink
new: Add download/unpack extensions. (#1)
Browse files Browse the repository at this point in the history
* Add impl.

* Update macros.

* Add common.

* Add dl crate.

* Polish.

* Use crates.

* Add download tests.

* Rename crates.

* Add unpack tests.

* Add github.

* Disable tests.

* Add features.
  • Loading branch information
milesj authored Jan 24, 2024
1 parent 27abb6a commit ccb5007
Show file tree
Hide file tree
Showing 21 changed files with 650 additions and 4 deletions.
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

0 comments on commit ccb5007

Please sign in to comment.