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: reproducible choice interactive #262

Merged
merged 32 commits into from
Dec 17, 2024
Merged

Conversation

dj8yfo
Copy link
Collaborator

@dj8yfo dj8yfo commented Dec 4, 2024

this will look now like the following

: cargo near build non-reproducible-wasm --help
Runs on current filesystem state without many restrictions
                                                                                                                                                             
Usage: cargo-near near build non-reproducible-wasm [OPTIONS]
                                                                                                                                                             
Options:
      --locked
      --no-release
      --no-abi
      --no-embed-abi
      --no-doc
      --no-wasmopt
      --out-dir <OUT_DIR>
      --manifest-path <MANIFEST_PATH>
      --features <FEATURES>
      --no-default-features
      --color <COLOR>                  [possible values: auto, always, never]
      --env <ENV>
  -h, --help                           Print help
  -V, --version                        Print version
: cargo near build reproducible-wasm --help
Requires `docker` config added and (git)committed to Cargo.toml, runs on clean (git)working tree state
                                                                                                                                                             
Usage: cargo-near near build reproducible-wasm [OPTIONS]
                                                                                                                                                             
Options:
      --no-locked
      --out-dir <OUT_DIR>
      --manifest-path <MANIFEST_PATH>
      --color <COLOR>                  [possible values: auto, always, never]
  -h, --help                           Print help
  -V, --version                        Print version

this is pending

Comment on lines +190 to +202
return Err(color_eyre::eyre::eyre!(
"{}\n`{}` for the used image:\n{}",
COMMAND_ERR_MSG,
serde_json::to_string(&default_cmd).unwrap(),
get_docker_image()
)
.note(format!(
"The default `{}` has changed since `{}` image\n\
See {}",
"container_build_command".cyan(),
"sourcescan/cargo-near:0.13.0-rust-1.83.0".cyan(),
"https://github.com/near/cargo-near/releases".cyan()
)));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would look like the following, if someone updates image and image_digest,
but doesn't update container_build_command (which stays to be ["cargo", "near", "build"]):

image

@dj8yfo
Copy link
Collaborator Author

dj8yfo commented Dec 9, 2024

has been tested on following cases:

sample-crate

  1. https://github.com/dj8yfo/sample_no_workspace/tree/test_interactive_command_no_docker => sample-crate-109.testnet ✔️

  2. sample-crate-110.testnet ✔️

sample-crate-110.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262@sha256:a231d4bf975d561a06dd5357f2ac03c883e8b3b510994f3b40c9b975dcdb02ce",
    "contract_path": "",
    "source_code_snapshot": "git+https://github.com/dj8yfo/sample_no_workspace?rev=0af334a86ea56d4257e6cc199231eb6a30950e69"
  },
  "link": "https://github.com/dj8yfo/sample_no_workspace/tree/0af334a86ea56d4257e6cc199231eb6a30950e69",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.7.7"
}

factories-like note

For both of the following factory-rust and neardevhub-contract the product-of-factories contracts can
be verified by SourceScan by explicitly adding package.metadata.near.reproducible_build, which is kept in sync with build script options.

(SourceScan runs cargo near build of version < 0.12.0 under the hood for the passed contract)

factory-rust

api example for build scripts (no change) - build.rs

  1. ok (same bs / image) repro-fct-80.testnet ✔️ , donation-product.repro-fct-80.testnet ✔️
repro-fct-80.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked",
      "--no-default-features",
      "--features",
      "near-sdk/expensive-debug"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "factory",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=91dde6ef874c7e0b74535c0b8cbd5d532d0caa99"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/91dde6ef874c7e0b74535c0b8cbd5d532d0caa99",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.1.13"
}

donation-product.repro-fct-80.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked",
      "--no-default-features"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "product-donation",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=91dde6ef874c7e0b74535c0b8cbd5d532d0caa99"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/91dde6ef874c7e0b74535c0b8cbd5d532d0caa99",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.2.9"
}

  1. new bs / older image: repro-fct-81.testnet ✔️ ,

donation-product.repro-fct-81.testnet

fails reproducibility verification, across breaking change boundary (builder version cargo-near-build 0.3.2 -> builder environment version cargo-near-build 0.3.0), 0.3.2 is current pr, to be published as 0.4.0

repro-fct-81.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "--no-default-features",
      "--features",
      "near-sdk/expensive-debug"
    ],
    "build_environment": "sourcescan/cargo-near:0.11.0-rust-1.82.0@sha256:6af67e796ff7182f6b184031f9e95d792f97b66693698abc51b4630acac0bf83",
    "contract_path": "factory",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=9c41cf040afb0c7c315a3b5efc14f95e0532325a"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/9c41cf040afb0c7c315a3b5efc14f95e0532325a",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.1.13"
}

donation-product.repro-fct-81.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked",
      "--no-default-features"
    ],
    "build_environment": "sourcescan/cargo-near:0.11.0-rust-1.82.0@sha256:6af67e796ff7182f6b184031f9e95d792f97b66693698abc51b4630acac0bf83",
    "contract_path": "product-donation",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=9c41cf040afb0c7c315a3b5efc14f95e0532325a"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/9c41cf040afb0c7c315a3b5efc14f95e0532325a",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.2.9"
}

repro-fct-product-81.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "--no-default-features"
    ],
    "build_environment": "sourcescan/cargo-near:0.11.0-rust-1.82.0@sha256:6af67e796ff7182f6b184031f9e95d792f97b66693698abc51b4630acac0bf83",
    "contract_path": "product-donation",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=9c41cf040afb0c7c315a3b5efc14f95e0532325a"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/9c41cf040afb0c7c315a3b5efc14f95e0532325a",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.2.9"
}

  1. old bs / newer image: repro-fct-82.testnet ✔️ ,
    donation-product.repro-fct-82.testnet

fails reproducibility verification, across breaking change boundary (builder version cargo-near-build 0.3.0 -> builder environment version cargo-near-build 0.3.2), 0.3.2 is current pr, to be published as 0.4.0

repro-fct-82.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked",
      "--no-default-features",
      "--features",
      "near-sdk/expensive-debug"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "factory",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=f9d5b4a3b3e5d17b44cbac4aa952f364fd5a6f68"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/f9d5b4a3b3e5d17b44cbac4aa952f364fd5a6f68",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.1.13"
}

donation-product.repro-fct-82.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "--no-default-features"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "product-donation",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=f9d5b4a3b3e5d17b44cbac4aa952f364fd5a6f68"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/f9d5b4a3b3e5d17b44cbac4aa952f364fd5a6f68",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.2.9"
}

repro-fct-product-82.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked",
      "--no-default-features"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "product-donation",
    "source_code_snapshot": "git+https://github.com/dj8yfo/factory-rust?rev=f9d5b4a3b3e5d17b44cbac4aa952f364fd5a6f68"
  },
  "link": "https://github.com/dj8yfo/factory-rust/tree/f9d5b4a3b3e5d17b44cbac4aa952f364fd5a6f68",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.2.9"
}

neardevhub

  1. no passed_env passed: community.devhub-inta.testnet ✔️ ,
    uniquehandle.community.devhub-inta.testnet ✔️ ,
    discussions.uniquehandle.community.devhub-inta.testnet ✔️
community.devhub-inta.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "community-factory",
    "source_code_snapshot": "git+https://github.com/dj8yfo/neardevhub-contract?rev=2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed"
  },
  "link": "https://github.com/dj8yfo/neardevhub-contract/tree/2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.1.0"
}

uniquehandle.community.devhub-inta.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "community",
    "source_code_snapshot": "git+https://github.com/dj8yfo/neardevhub-contract?rev=2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed"
  },
  "link": "https://github.com/dj8yfo/neardevhub-contract/tree/2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.1.0"
}

discussions.uniquehandle.community.devhub-inta.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "discussions",
    "source_code_snapshot": "git+https://github.com/dj8yfo/neardevhub-contract?rev=2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed"
  },
  "link": "https://github.com/dj8yfo/neardevhub-contract/tree/2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.1.0"
}

  1. 2 vars passes into passed_env: community.devhub-intb.testnet
community.devhub-intb.testnet

{
  "build_info": {
    "build_command": [
      "cargo",
      "near",
      "build",
      "non-reproducible-wasm",
      "--locked",
      "--env",
      "KEY=VALUE",
      "--env",
      "GOOGLE_QUERY=https://www.google.com/search?q=google+translate&sca_esv=3c150c50f502bc5d"
    ],
    "build_environment": "dj8yfo/sourcescan:0.x.x-dev-pr-262-1.83@sha256:b38d13fb8c3dfe4d8555303907f8ea47be8df7bf65ee452817af5ae0c54cdc51",
    "contract_path": "community-factory",
    "source_code_snapshot": "git+https://github.com/dj8yfo/neardevhub-contract?rev=2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed"
  },
  "link": "https://github.com/dj8yfo/neardevhub-contract/tree/2716b484b35dbe1deed8d5dbfb9ac39f5bec3fed",
  "standards": [
    {
      "standard": "nep330",
      "version": "1.2.0"
    }
  ],
  "version": "0.1.0"
}

@dj8yfo
Copy link
Collaborator Author

dj8yfo commented Dec 10, 2024

@race-of-sloths include

@race-of-sloths
Copy link

race-of-sloths commented Dec 10, 2024

@dj8yfo Thank you for your contribution! Your pull request is now a part of the Race of Sloths!
We are launching a survey "Who is faster? You vs SpaceX"

Shows inviting banner with latest news.

Shows profile picture for the author of the PR

Current status: executed
Reviewer Score
@frol 13

Your contribution is much appreciated with a final score of 13!
You have received 299 (130 base + 50 weekly bonus + 80 monthly bonus + 15% lifetime bonus) Sloth points for this contribution

@frol received 25 Sloth Points for reviewing and scoring this pull request.

Congratulations @dj8yfo! Your PR was highly scored and you completed another monthly streak! To keep your monthly streak make another pull request next month and get 8+ score for it

What is the Race of Sloths

Race of Sloths is a friendly competition where you can participate in challenges and compete with other open-source contributors within your normal workflow

For contributors:

  • Tag @race-of-sloths inside your pull requests
  • Wait for the maintainer to review and score your pull request
  • Check out your position in the Leaderboard
  • Keep weekly and monthly streaks to reach higher positions
  • Boast your contributions with a dynamic picture of your Profile

For maintainers:

  • Score pull requests that participate in the Race of Sloths and receive a reward
  • Engage contributors with fair scoring and fast responses so they keep their streaks
  • Promote the Race to the point where the Race starts promoting you
  • Grow the community of your contributors

Feel free to check our website for additional details!

Bot commands
  • For contributors
    • Include a PR: @race-of-sloths include to enter the Race with your PR
  • For maintainers:
    • Invite contributor @race-of-sloths invite to invite the contributor to participate in a race or include it, if it's already a runner.
    • Assign points: @race-of-sloths score [1/2/3/5/8/13] to award points based on your assessment.
    • Reject this PR: @race-of-sloths exclude to send this PR back to the drawing board.
    • Exclude repo: @race-of-sloths pause to stop bot activity in this repo until @race-of-sloths unpause command is called

@dj8yfo dj8yfo marked this pull request as ready for review December 11, 2024 23:04
of not ouputting full transaction to console
cargo-near/src/commands/abi/mod.rs Outdated Show resolved Hide resolved
cargo-near/src/commands/build/mod.rs Outdated Show resolved Hide resolved
cargo-near/src/commands/deploy/mod.rs Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
Copy link
Contributor

@frol frol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing!

@race-of-sloths score 13

@dj8yfo dj8yfo merged commit a63fb95 into main Dec 17, 2024
17 checks passed
@dj8yfo dj8yfo deleted the if-reproducible-interactive branch December 17, 2024 11:21
@frol frol mentioned this pull request Dec 17, 2024
dj8yfo pushed a commit that referenced this pull request Dec 17, 2024
## 🤖 New release
* `cargo-near`: 0.12.2 -> 0.13.0 (⚠️ API breaking changes)
* `cargo-near-build`: 0.3.2 -> 0.4.0 (⚠️ API breaking changes)

### ⚠️ `cargo-near` breaking changes

```
--- failure module_missing: pub module removed or renamed ---

Description:
A publicly-visible module cannot be imported by its prior path. A `pub use` may have been removed, or the module may have been renamed, removed, or made non-public.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.37.0/src/lints/module_missing.ron

Failed in:
  mod cargo_near::commands::build_command, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/build_command/mod.rs:1
  mod cargo_near::commands::abi_command, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/abi_command/mod.rs:1

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.37.0/src/lints/struct_missing.ron

Failed in:
  struct cargo_near::commands::abi_command::AbiCommandlContext, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/abi_command/mod.rs:45
  struct cargo_near::commands::deploy::CliContract, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/deploy/mod.rs:5
  struct cargo_near::commands::abi_command::AbiCommand, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/abi_command/mod.rs:6
  struct cargo_near::commands::build_command::InteractiveClapContextScopeForBuildCommand, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/build_command/mod.rs:6
  struct cargo_near::commands::abi_command::CliAbiCommand, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/abi_command/mod.rs:3
  struct cargo_near::commands::build_command::CliBuildCommand, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/build_command/mod.rs:6
  struct cargo_near::commands::build_command::BuildCommandlContext, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/build_command/mod.rs:173
  struct cargo_near::commands::deploy::ContractContext, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/deploy/mod.rs:24
  struct cargo_near::commands::deploy::InteractiveClapContextScopeForContract, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/deploy/mod.rs:5
  struct cargo_near::commands::abi_command::InteractiveClapContextScopeForAbiCommand, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/abi_command/mod.rs:3
  struct cargo_near::commands::deploy::Contract, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/deploy/mod.rs:9
  struct cargo_near::commands::build_command::BuildCommand, previously in file /tmp/.tmpamrxDt/cargo-near/src/commands/build_command/mod.rs:9
```

### ⚠️ `cargo-near-build` breaking changes

```
--- failure struct_pub_field_missing: pub struct's pub field removed or renamed ---

Description:
A publicly-visible struct has at least one public field that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.37.0/src/lints/struct_pub_field_missing.ron

Failed in:
  field no_release of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:20
  field no_abi of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:23
  field no_embed_abi of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:26
  field no_doc of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:29
  field no_wasmopt of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:32
  field features of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:39
  field no_default_features of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:42
  field cli_description of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:49
  field env of struct Opts, previously in file /tmp/.tmpamrxDt/cargo-near-build/src/types/near/docker_build/mod.rs:53
```

<details><summary><i><b>Changelog</b></i></summary><p>

## `cargo-near`
<blockquote>

##
[0.13.0](cargo-near-v0.12.2...cargo-near-v0.13.0)
- 2024-12-17

### Added

- reproducible choice interactive (#262)

### Other

- update `cargo near new` template `image` and `image_digest`
([#259](#259))
- update `cargo near new` template `image` and `image_digest`
([#257](#257))
</blockquote>

## `cargo-near-build`
<blockquote>

##
[0.4.0](cargo-near-build-v0.3.2...cargo-near-build-v0.4.0)
- 2024-12-17

### Added

- reproducible choice interactive (#262)

### Other

- fix 1.83clippy, audit (#260)
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants