Skip to content

Commit

Permalink
feat: New command to initialize a new smart contract project (#117)
Browse files Browse the repository at this point in the history
Resolves #100

---------

Co-authored-by: Vlad Frolov <frolvlad@gmail.com>
  • Loading branch information
FroVolod and frol authored Nov 20, 2023
1 parent 4e56a2e commit ed944de
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 11 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/release-plz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
token: ${{ secrets.MY_GITHUB_TOKEN }}
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
Expand Down
18 changes: 13 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CI

on:
push:
branches: [ main ]
branches: [main]
pull_request:

jobs:
Expand All @@ -15,7 +15,9 @@ jobs:

steps:
- name: Checkout Sources
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive

- name: Get MSRV
run: |
Expand Down Expand Up @@ -45,7 +47,9 @@ jobs:

steps:
- name: Checkout Sources
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive

- name: "Install stable Rust toolchain"
uses: actions-rs/toolchain@v1
Expand All @@ -69,7 +73,9 @@ jobs:

steps:
- name: Checkout Sources
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive

- name: Check Formatting
run: cargo fmt -- --check
Expand All @@ -86,7 +92,9 @@ jobs:

steps:
- name: Checkout Sources
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Audit Tool
run: cargo install cargo-audit
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "cargo-near/src/commands/new/new-project-template"]
path = cargo-near/src/commands/new/new-project-template
url = https://github.com/near/cargo-near-new-project-template
4 changes: 2 additions & 2 deletions Cargo.lock

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

6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as below, without any additional terms or conditions.

Note, fetching the git repository of cargo-near, don't forget to pull the submodules after cloning:

```console
git submodule update --init
```

## License

Licensed under either of
Expand Down
6 changes: 6 additions & 0 deletions cargo-near/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod abi_command;
pub mod build_command;
pub mod create_dev_account;
pub mod deploy;
pub mod new;

#[derive(Debug, EnumDiscriminants, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(context = near_cli_rs::GlobalContext)]
Expand All @@ -12,6 +13,11 @@ pub mod deploy;
#[non_exhaustive]
/// What are you up to? (select one of the options with the up-down arrows on your keyboard and press Enter)
pub enum NearCommand {
#[strum_discriminants(strum(
message = "new - Initializes a new project to create a contract"
))]
/// Initializes a new project to create a contract
New(self::new::New),
#[strum_discriminants(strum(
message = "build - Build a NEAR contract and optionally embed ABI"
))]
Expand Down
103 changes: 103 additions & 0 deletions cargo-near/src/commands/new/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use color_eyre::eyre::{ContextCompat, WrapErr};

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = near_cli_rs::GlobalContext)]
#[interactive_clap(output_context = NewContext)]
pub struct New {
/// Enter a new project name (path to the project) to create a contract:
pub project_dir: near_cli_rs::types::path_buf::PathBuf,
}

#[derive(Debug, Clone)]
pub struct NewContext;

impl NewContext {
pub fn from_previous_context(
_previous_context: near_cli_rs::GlobalContext,
scope: &<New as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
) -> color_eyre::eyre::Result<Self> {
let project_dir: &std::path::Path = scope.project_dir.as_ref();
let project_name = project_dir
.file_name()
.wrap_err("Could not extract project name from project path")?
.to_str()
.wrap_err("Project name has to be a valid UTF-8 string")?;

for new_project_file in NEW_PROJECT_FILES {
let new_file_path = project_dir.join(new_project_file.file_path);
std::fs::create_dir_all(new_file_path.parent().wrap_err_with(|| {
format!("Impossible to get parent for `{}`", new_file_path.display())
})?)?;
std::fs::write(
&new_file_path,
new_project_file
.content
.replace("cargo-near-new-project-name", project_name),
)
.wrap_err_with(|| format!("Failed to write to file: {}", new_file_path.display()))?;
}

std::process::Command::new("git")
.arg("init")
.current_dir(project_dir)
.output()
.wrap_err("Failed to execute process: `git init`")?;

println!("New project is created at '{}'\n", project_dir.display());
println!("Now you can build, deploy, and finish CI setup for automatic deployment:");
println!("1. `cargo near build`");
println!("2. `cargo test`");
println!("3. `cargo near deploy`");
println!("4. Configure `NEAR_CONTRACT_STAGING_*` and `NEAR_CONTRACT_PRODUCTION_*` variables and secrets on GitHub to enable automatic deployment to staging and production. See more details in `.github/workflow/*` files.");

Ok(Self)
}
}

struct NewProjectFile {
file_path: &'static str,
content: &'static str,
}

const NEW_PROJECT_FILES: &[NewProjectFile] = &[
NewProjectFile {
file_path: ".github/workflows/deploy-production.yml",
content: include_str!("new-project-template/.github/workflows/deploy-production.yml"),
},
NewProjectFile {
file_path: ".github/workflows/deploy-staging.yml",
content: include_str!("new-project-template/.github/workflows/deploy-staging.yml"),
},
NewProjectFile {
file_path: ".github/workflows/test.yml",
content: include_str!("new-project-template/.github/workflows/test.yml"),
},
NewProjectFile {
file_path: ".github/workflows/undeploy-staging.yml",
content: include_str!("new-project-template/.github/workflows/undeploy-staging.yml"),
},
NewProjectFile {
file_path: "src/lib.rs",
content: include_str!("new-project-template/src/lib.rs"),
},
NewProjectFile {
file_path: "tests/test_basics.rs",
content: include_str!("new-project-template/tests/test_basics.rs"),
},
NewProjectFile {
file_path: ".gitignore",
content: include_str!("new-project-template/.gitignore"),
},
NewProjectFile {
file_path: "Cargo.toml",
content: include_str!("new-project-template/Cargo.toml"),
},
NewProjectFile {
file_path: "README.md",
content: include_str!("new-project-template/README.md"),
},
NewProjectFile {
file_path: "rust-toolchain.toml",
content: include_str!("new-project-template/rust-toolchain.toml"),
},
];
1 change: 1 addition & 0 deletions cargo-near/src/commands/new/new-project-template
Submodule new-project-template added at 9d5349
2 changes: 1 addition & 1 deletion cargo-near/src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,12 @@ pub(crate) fn compile_project(
let dylib_files = compile_artifact
.filenames
.iter()
.cloned()
.filter(|f| {
f.extension()
.map(|e| e == artifact_extension)
.unwrap_or(false)
})
.cloned()
.collect();
let mut dylib_files_iter = Vec::into_iter(dylib_files);
match (dylib_files_iter.next(), dylib_files_iter.next()) {
Expand Down
3 changes: 1 addition & 2 deletions integration-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ macro_rules! invoke_cargo_near {
};
cargo_near::commands::build_command::build::run(args)?;
},
Some(cargo_near::commands::CliNearCommand::CreateDevAccount(_)) => todo!(),
Some(cargo_near::commands::CliNearCommand::Deploy(_)) => todo!(),
Some(_) => todo!(),
None => ()
}

Expand Down

0 comments on commit ed944de

Please sign in to comment.