Skip to content

Commit

Permalink
ci: cargo near new integration test + gh workflow to autorenew image …
Browse files Browse the repository at this point in the history
…tag/digest (#235)
  • Loading branch information
dj8yfo authored Oct 28, 2024
1 parent 634877a commit 7657e22
Show file tree
Hide file tree
Showing 21 changed files with 463 additions and 644 deletions.
53 changes: 53 additions & 0 deletions .github/workflows/crontab_new_template_renewal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: renew docker image tag and digest periodically and on-demand

on:
schedule:
- cron: '0 1 * * *' # Runs daily at 1 hour after midnight
workflow_dispatch:

permissions:
pull-requests: write
contents: write

jobs:
check_latest_docker_image:
runs-on: ubuntu-latest

steps:
- name: Check out the main branch
uses: actions/checkout@v4
with:
ref: main

- uses: hustcer/setup-nu@v3
with:
version: "*"

- name: Run update script
shell: nu {0}
run: |
let record = http get "https://hub.docker.com/v2/namespaces/sourcescan/repositories/cargo-near/tags" | get results | first;
let mod_content = (
open cargo-near/src/commands/new/new-project-template/Cargo.toml.template --raw | lines
| each {
|line| if ($line | str starts-with "image = ") {
$'image = "sourcescan/cargo-near:($record.name)"'
} else { $line }
}
| each {
|line| if ($line | str starts-with "image_digest = ") {
$'image_digest = "($record.digest)"'
} else { $line }
}
| to text
);
$mod_content | save -f cargo-near/src/commands/new/new-project-template/Cargo.toml.template
git diff
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
title: update `cargo near new` template `image` and `image_digest`
13 changes: 10 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ jobs:
run: sudo apt-get update && sudo apt-get install --assume-yes libudev-dev

- name: Cargo check
env:
# info: (overridden by '/home/runner/work/cargo-near/cargo-near/rust-toolchain.toml')
RUSTUP_TOOLCHAIN: ${{ env.RUST_MSRV }}
run: |
rustc -vV
cargo check -p cargo-near
cargo check -p cargo-near-build --all-features
Expand All @@ -56,9 +60,9 @@ jobs:
- name: "Install stable Rust toolchain"
uses: actions-rs/toolchain@v1
with:
profile: minimal
# channel is really controlled by ./rust-toolchain.toml
toolchain: stable
default: true
profile: minimal

- name: Install `wasm32-unknown-unknown`
run: rustup target add wasm32-unknown-unknown
Expand All @@ -68,7 +72,10 @@ jobs:
run: sudo apt-get update && sudo apt-get install --assume-yes libudev-dev

- name: Run tests
run: cargo test --workspace
run: |
git config --global user.email "[email protected]"
git config --global user.name "nearprotocol-ci"
cargo test --workspace
lint:
runs-on: ubuntu-latest
Expand Down
36 changes: 20 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cargo-near-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,4 @@ docker = [
"dep:nix",
"dep:shell-words",
]
test_code = []
3 changes: 3 additions & 0 deletions cargo-near-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ pub mod docker {
pub use crate::types::near::docker_build::Opts as DockerBuildOpts;
}

#[cfg(feature = "test_code")]
pub use crate::types::cargo::metadata::CrateMetadata;

pub use bon;
pub use camino;
pub use near_abi;
75 changes: 68 additions & 7 deletions cargo-near-build/src/types/cargo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{thread, time::Duration};
use camino::Utf8PathBuf;
use cargo_metadata::{MetadataCommand, Package};
use colored::Colorize;
use eyre::{ContextCompat, WrapErr};
use eyre::{ContextCompat, OptionExt, WrapErr};

use crate::types::near::build::buildtime_env;

Expand All @@ -25,11 +25,14 @@ impl CrateMetadata {
no_locked: bool,
cargo_target_dir: Option<&buildtime_env::CargoTargetDir>,
) -> eyre::Result<Self> {
let (mut metadata, root_package) =
get_cargo_metadata(&manifest_path, no_locked, cargo_target_dir)?;

metadata.target_directory = crate::fs::force_canonicalize_dir(&metadata.target_directory)?;
metadata.workspace_root = metadata.workspace_root.canonicalize_utf8()?;
let (metadata, root_package) = {
let (mut metadata, root_package) =
get_cargo_metadata(&manifest_path, no_locked, cargo_target_dir)?;
metadata.target_directory =
crate::fs::force_canonicalize_dir(&metadata.target_directory)?;
metadata.workspace_root = metadata.workspace_root.canonicalize_utf8()?;
(metadata, root_package)
};

let mut target_directory =
crate::fs::force_canonicalize_dir(&metadata.target_directory.join("near"))?;
Expand Down Expand Up @@ -71,6 +74,60 @@ impl CrateMetadata {
pub fn formatted_package_name(&self) -> String {
self.root_package.name.replace('-', "_")
}

pub fn find_direct_dependency(
&self,
dependency_name: &str,
) -> eyre::Result<Vec<&cargo_metadata::Package>> {
let Some(ref dependency_graph) = self.raw_metadata.resolve else {
return Err(eyre::eyre!(
"crate_metadata.raw_metadata.resolve dependency graph is expected to be set\n\
it's not set when `cargo metadata` was run with `--no-deps` flag"
));
};
let Some(ref root_package_id) = dependency_graph.root else {
return Err(eyre::eyre!(
"crate_metadata.raw_metadata.resolve.root package id is expected to be set\n\
it's not set when `cargo metadata` was run from a root of virtual workspace"
));
};

let root_nodes = dependency_graph
.nodes
.iter()
.filter(|node| node.id == *root_package_id)
.collect::<Vec<_>>();

if root_nodes.len() != 1 {
return Err(eyre::eyre!(
"expected to find extactly 1 root node in dependency graph: {:#?}",
root_nodes
));
}
let root_node = root_nodes[0];

let dependency_nodes = root_node
.deps
.iter()
.filter(|dep| dep.name == dependency_name)
.collect::<Vec<_>>();

let mut result = vec![];

for dependency_node in dependency_nodes {
let dependency_package = self
.raw_metadata
.packages
.iter()
.find(|pkg| pkg.id == dependency_node.pkg)
.ok_or_eyre(format!(
"expected to find a package for package id : {:#?}",
dependency_node.pkg
))?;
result.push(dependency_package);
}
Ok(result)
}
}

/// Get the result of `cargo metadata`, together with the root package id.
Expand Down Expand Up @@ -112,7 +169,11 @@ fn get_cargo_metadata(
.wrap_err("Error invoking `cargo metadata`. Your `Cargo.toml` file is likely malformed")?;
let root_package = metadata
.root_package()
.wrap_err("Error invoking `cargo metadata`. Your `Cargo.toml` file is likely malformed")?
.wrap_err(
"raw_metadata.root_package() returned None.\n\
Command was likely called from a root of virtual workspace as current directory \
and not from a contract's crate",
)?
.clone();
Ok((metadata, root_package))
}
2 changes: 1 addition & 1 deletion cargo-near/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "cargo-near"
version = "0.10.1"
authors = ["Near Inc <[email protected]>"]
edition = "2021"
rust-version = "1.78.0"
rust-version = "1.79.0"
description = "Cargo extension for building Rust smart contracts on NEAR"
readme = "README.md"
repository = "https://github.com/near/cargo-near"
Expand Down
19 changes: 13 additions & 6 deletions cargo-near/src/commands/new/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ impl NewContext {
.replace(
"cargo-near-new-ci-tool-version-self",
env!("CARGO_PKG_VERSION"),
)
.replace(
"TEST_BASICS_ON_INCLUDE",
include_str!("./test_basics_on.rs.in"),
),
)
.wrap_err_with(|| format!("Failed to write to file: {}", new_file_path.display()))?;
Expand Down Expand Up @@ -96,17 +100,20 @@ impl NewContext {
));
}

let status = std::process::Command::new("git")
let child = std::process::Command::new("git")
.arg("commit")
.arg("-m")
.arg("init")
.arg("--author=nearprotocol-ci <[email protected]>")
.current_dir(project_dir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()?;
if !status.success() {
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
let output = child.wait_with_output()?;
if !output.status.success() {
println!("{}", String::from_utf8_lossy(&output.stderr));
return Err(color_eyre::eyre::eyre!(
"Failed to execute process: `git commit -m init`"
"Failed to execute process: `git commit -m init --author='nearprotocol-ci <[email protected]>'`"
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ near-sdk = "5.4"

[dev-dependencies]
near-sdk = { version = "5.5", features = ["unit-testing"] }
near-workspaces = { version = "0.14.0", features = ["unstable"] }
near-workspaces = { version = "0.14.1", features = ["unstable"] }
tokio = { version = "1.12.0", features = ["full"] }
serde_json = "1"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,11 @@ use serde_json::json;

#[tokio::test]
async fn test_contract_is_operational() -> Result<(), Box<dyn std::error::Error>> {
let sandbox = near_workspaces::sandbox().await?;
let contract_wasm = near_workspaces::compile_project("./").await?;

let contract = sandbox.dev_deploy(&contract_wasm).await?;

let user_account = sandbox.dev_create_account().await?;

let outcome = user_account
.call(contract.id(), "set_greeting")
.args_json(json!({"greeting": "Hello World!"}))
.transact()
.await?;
assert!(outcome.is_success());

let user_message_outcome = contract.view("get_greeting").args_json(json!({})).await?;
assert_eq!(user_message_outcome.json::<String>()?, "Hello World!");

test_basics_on(&contract_wasm).await?;
Ok(())
}

TEST_BASICS_ON_INCLUDE

Loading

0 comments on commit 7657e22

Please sign in to comment.