Skip to content

Commit

Permalink
refactor(language.rust): check wasmwasi target and return error if mi…
Browse files Browse the repository at this point in the history
…smatched

Breaking change to support Rust 1.84 and newer

BREAKING CHANGE:
Only the wasm32-waip1 build target is accepted if a non default config is provided
  • Loading branch information
anthony-gomez-fastly committed Feb 6, 2025
1 parent 9679de4 commit cca0fc1
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 26 deletions.
4 changes: 2 additions & 2 deletions .fastly/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ toolchain_constraint = ">= 1.21" # Go toolchain constraint for use wit
toolchain_constraint_tinygo = ">= 1.18" # Go toolchain constraint for use with TinyGo.

[language.rust]
toolchain_constraint = ">= 1.56.1, <1.84.0"
wasm_wasi_target = "wasm32-wasi"
toolchain_constraint = ">= 1.78.0"
wasm_wasi_target = "wasm32-wasip1"

[wasm-tools]
ttl = "24h"
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/pr_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- name: "Checkout code"
uses: actions/checkout@v4
- name: "Install Rust"
uses: dtolnay/rust-toolchain@1.83.0 # to install tq via `make config`
uses: dtolnay/rust-toolchain@stable
- name: "Generate static app config"
run: make config
- name: "Config Artifact"
Expand All @@ -25,7 +25,7 @@ jobs:
- name: "Checkout code"
uses: actions/checkout@v4
- name: "Install Rust"
uses: dtolnay/rust-toolchain@1.83.0 # to install tq via `make config`
uses: dtolnay/rust-toolchain@stable
- name: Install Go
uses: actions/setup-go@v5
with:
Expand Down Expand Up @@ -124,11 +124,11 @@ jobs:
path: ${{ steps.go-cache-paths.outputs.gomod }}
key: ${{ runner.os }}-test-go-mod-${{ hashFiles('**/go.sum') }}
- name: "Install Rust"
uses: dtolnay/rust-toolchain@1.83.0
- name: "Add wasm32-wasi Rust target"
run: rustup target add wasm32-wasi --toolchain 1.83.0
uses: dtolnay/rust-toolchain@stable
- name: "Add wasm32-wasip1 Rust target"
run: rustup target add wasm32-wasip1 --toolchain stable
- name: "Validate Rust toolchain"
run: rustup show && rustup target list --installed --toolchain 1.83.0
run: rustup show && rustup target list --installed --toolchain stable
shell: bash
- name: "Install Node"
uses: actions/setup-node@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tag_to_draft_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: "Set GOHOSTOS and GOHOSTARCH"
run: echo "GOHOSTOS=$(go env GOHOSTOS)" >> $GITHUB_ENV && echo "GOHOSTARCH=$(go env GOHOSTARCH)" >> $GITHUB_ENV
- name: "Install Rust"
uses: dtolnay/rust-toolchain@1.83.0
uses: dtolnay/rust-toolchain@stable
- name: "Generate static app config"
run: make config
# Passing the raw SSH private key causes an error:
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile-rust
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
FROM rust:latest
LABEL maintainer="Fastly OSS <oss@fastly.com>"

ENV RUST_TOOLCHAIN=1.83.0
ENV RUST_TOOLCHAIN=stable
RUN rustup toolchain install ${RUST_TOOLCHAIN} \
&& rustup target add wasm32-wasi --toolchain ${RUST_TOOLCHAIN} \
&& rustup target add wasm32-wasip1 --toolchain ${RUST_TOOLCHAIN} \
&& apt-get update && apt-get install -y curl jq && apt-get -y clean && rm -rf /var/lib/apt/lists/* \
&& export FASTLY_CLI_VERSION=$(curl -s https://api.github.com/repos/fastly/cli/releases/latest | jq -r .tag_name | cut -d 'v' -f 2) \
GOARCH=$(dpkg --print-architecture) \
Expand Down
2 changes: 1 addition & 1 deletion TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ TEST_COMPUTE_BUILD_RUST=1 make test TEST_ARGS="-run TestBuildRust/fastly_crate_p

When running the tests locally, if you don't have the relevant language ecosystems set-up properly then the tests will fail to run and you'll need to review the code to see what the remediation steps are, as that output doesn't get shown when running the test suite.

> **NOTE**: you might notice a discrepancy between CI and your local environment which is caused by the difference in Rust toolchain versions as defined in .github/workflows/pr_test.yml which specifies the version required to be tested for in CI. Running `rustup toolchain install <version>` and `rustup target add wasm32-wasi --toolchain <version>` will resolve any failing integration tests you may be running locally.
> **NOTE**: you might notice a discrepancy between CI and your local environment which is caused by the difference in Rust toolchain versions as defined in .github/workflows/pr_test.yml which specifies the version required to be tested for in CI. Running `rustup toolchain install <version>` and `rustup target add wasm32-wasip1 --toolchain <version>` will resolve any failing integration tests you may be running locally.
To the run the full test suite:

Expand Down
42 changes: 35 additions & 7 deletions pkg/commands/compute/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ func TestBuildRust(t *testing.T) {
Profiles: testutil.TokenProfile(),
Language: config.Language{
Rust: config.Rust{
ToolchainConstraint: ">= 1.54.0",
WasmWasiTarget: "wasm32-wasi",
ToolchainConstraint: ">= 1.78.0",
WasmWasiTarget: "wasm32-wasip1",
},
},
},
Expand Down Expand Up @@ -102,8 +102,8 @@ func TestBuildRust(t *testing.T) {
Profiles: testutil.TokenProfile(),
Language: config.Language{
Rust: config.Rust{
ToolchainConstraint: ">= 1.54.0",
WasmWasiTarget: "wasm32-wasi",
ToolchainConstraint: ">= 1.78.0",
WasmWasiTarget: "wasm32-wasip1",
},
},
},
Expand All @@ -123,6 +123,34 @@ func TestBuildRust(t *testing.T) {
build = "echo no compilation happening"`,
wantRemediationError: compute.DefaultBuildErrorRemediation,
},
{
name: "wasmwasi target error",
args: args("compute build --verbose"),
applicationConfig: &config.File{
Profiles: testutil.TokenProfile(),
Language: config.Language{
Rust: config.Rust{
ToolchainConstraint: ">= 1.78.0",
WasmWasiTarget: "wasm32-wasi",
},
},
},
cargoManifest: `
[package]
name = "fastly-compute-project"
version = "0.1.0"
[dependencies]
fastly = "=0.6.0"`,
fastlyManifest: fmt.Sprintf(`
manifest_version = 2
name = "test"
language = "rust"
[scripts]
build = "%s"`, fmt.Sprintf(compute.RustDefaultBuildCommand, compute.RustDefaultPackageName, compute.RustWasmWasiTarget)),
wantError: "your .cargo/config.toml file is configured to produce a wasm32-wasi binary, but that is not supported. It must be configured to produce a wasm32-wasip1 binary",
},
// NOTE: This test passes --verbose so we can validate specific outputs.
{
name: "successful build",
Expand All @@ -131,8 +159,8 @@ func TestBuildRust(t *testing.T) {
Profiles: testutil.TokenProfile(),
Language: config.Language{
Rust: config.Rust{
ToolchainConstraint: ">= 1.54.0",
WasmWasiTarget: "wasm32-wasi",
ToolchainConstraint: ">= 1.78.0",
WasmWasiTarget: "wasm32-wasip1",
},
},
},
Expand All @@ -149,7 +177,7 @@ func TestBuildRust(t *testing.T) {
language = "rust"
[scripts]
build = "%s"`, fmt.Sprintf(compute.RustDefaultBuildCommand, compute.RustDefaultPackageName)),
build = "%s"`, fmt.Sprintf(compute.RustDefaultBuildCommand, compute.RustDefaultPackageName, compute.RustWasmWasiTarget)),
wantOutput: []string{
"Creating ./bin directory (for Wasm binary)",
"Built package",
Expand Down
22 changes: 15 additions & 7 deletions pkg/commands/compute/language_rust.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ import (
// NOTE: In the 5.x CLI releases we persisted the default to the fastly.toml
// We no longer do that. In 6.x we use the default and just inform the user.
// This makes the experience less confusing as users didn't expect file changes.
const RustDefaultBuildCommand = "cargo build --bin %s --release --target wasm32-wasi --color always"
const RustDefaultBuildCommand = "cargo build --bin %s --release --target %s --color always"

// RustWasmWasiTarget is the expected Rust WasmWasi build target
const RustWasmWasiTarget = "wasm32-wasip1"

// RustManifest is the manifest file for defining project configuration.
const RustManifest = "Cargo.toml"
Expand Down Expand Up @@ -144,12 +147,17 @@ func (r *Rust) Dependencies() map[string]string {

// Build compiles the user's source code into a Wasm binary.
func (r *Rust) Build() error {
var wasmWasiTarget = r.config.WasmWasiTarget
if wasmWasiTarget != RustWasmWasiTarget {
return fmt.Errorf("your .cargo/config.toml file is configured to produce a %s binary, but that is not supported. It must be configured to produce a %s binary", wasmWasiTarget, RustWasmWasiTarget)
}

if r.build == "" {
r.build = fmt.Sprintf(RustDefaultBuildCommand, RustDefaultPackageName)
r.build = fmt.Sprintf(RustDefaultBuildCommand, RustDefaultPackageName, wasmWasiTarget)
r.defaultBuild = true
}

err := r.modifyCargoPackageName(r.defaultBuild)
err := r.modifyCargoPackageName(r.defaultBuild, wasmWasiTarget)
if err != nil {
return err
}
Expand Down Expand Up @@ -204,7 +212,7 @@ type RustToolchain struct {
// modifyCargoPackageName validates whether the --bin flag matches the
// Cargo.toml package name. If it doesn't match, update the default build script
// to match.
func (r *Rust) modifyCargoPackageName(noBuildScript bool) error {
func (r *Rust) modifyCargoPackageName(noBuildScript bool, wasmWasiTarget string) error {
s := "cargo locate-project --quiet"
args := strings.Split(s, " ")

Expand Down Expand Up @@ -255,7 +263,7 @@ func (r *Rust) modifyCargoPackageName(noBuildScript bool) error {
// If user has a Cargo Workspace AND no custom script.
// We need to identify which Workspace package is their application.
// Then extract the package name from its Cargo.toml manifest.
// We do this by checking for a rust-toolchain.toml containing a wasm32-wasi target.
// We do this by checking for a rust-toolchain.toml containing a wasm32-wasip1 target.
//
// NOTE: This logic will need to change in the future.
// Specifically, when we support linking multiple Wasm binaries.
Expand All @@ -270,7 +278,7 @@ func (r *Rust) modifyCargoPackageName(noBuildScript bool) error {
if err != nil {
return fmt.Errorf("failed to unmarshal '%s' data: %w", rustToolchainFile, err)
}
if len(rtm.Toolchain.Targets) > 0 && rtm.Toolchain.Targets[0] == "wasm32-wasi" {
if len(rtm.Toolchain.Targets) > 0 && rtm.Toolchain.Targets[0] == "wasm32-wasip1" {
var cm CargoManifest
err := cm.Read(filepath.Join(m, "Cargo.toml"))
if err != nil {
Expand All @@ -294,7 +302,7 @@ func (r *Rust) modifyCargoPackageName(noBuildScript bool) error {

// Ensure the default build script matches the Cargo.toml package name.
if noBuildScript && r.packageName != "" && r.packageName != RustDefaultPackageName {
r.build = fmt.Sprintf(RustDefaultBuildCommand, r.packageName)
r.build = fmt.Sprintf(RustDefaultBuildCommand, r.packageName, wasmWasiTarget)
}

return nil
Expand Down

0 comments on commit cca0fc1

Please sign in to comment.