Skip to content

CI Pipeline Compatibility #124

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 74 additions & 62 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class RustPlugin {
dockerTag: DEFAULT_DOCKER_TAG,
dockerImage: DEFAULT_DOCKER_IMAGE,
dockerless: false,
strictMode: true,
},
(this.serverless.service.custom && this.serverless.service.custom.rust) ||
{}
Expand Down Expand Up @@ -74,15 +75,13 @@ class RustPlugin {
""
).split(/\s+/);

let target = (funcArgs || {}).target || this.custom.target;

let target = (funcArgs || {}).target || this.custom.target

const targetArgs =
target ?
['--target', target]
: MUSL_PLATFORMS.includes(platform)
? ["--target", "x86_64-unknown-linux-musl"]
: [];
const targetArgs = target
? ["--target", target]
: MUSL_PLATFORMS.includes(platform)
? ["--target", "x86_64-unknown-linux-musl"]
: [];
return [
...defaultArgs,
...profileArgs,
Expand All @@ -94,30 +93,29 @@ class RustPlugin {
localBuildEnv(funcArgs, env, platform) {
const defaultEnv = { ...env };

let target = (funcArgs || {}).target || this.custom.target
let linker = (funcArgs || {}).linker || this.custom.linker
let target = (funcArgs || {}).target || this.custom.target;
let linker = (funcArgs || {}).linker || this.custom.linker;

const platformEnv =
linker ?
{
const platformEnv = linker
? {
RUSTFLAGS: (env["RUSTFLAGS"] || "") + ` -Clinker=${linker}`,
TARGET_CC: linker,
[`CC_${target || 'x86_64_unknown_linux_musl'}`]: linker,
[`CC_${target || "x86_64_unknown_linux_musl"}`]: linker,
}
: "win32" === platform
? {
RUSTFLAGS: (env["RUSTFLAGS"] || "") + " -Clinker=rust-lld",
TARGET_CC: "rust-lld",
CC_x86_64_unknown_linux_musl: "rust-lld",
}
: "win32" === platform
? {
RUSTFLAGS: (env["RUSTFLAGS"] || "") + " -Clinker=rust-lld",
TARGET_CC: "rust-lld",
CC_x86_64_unknown_linux_musl: "rust-lld",
}
: "darwin" === platform
? {
RUSTFLAGS:
(env["RUSTFLAGS"] || "") + " -Clinker=x86_64-linux-musl-gcc",
TARGET_CC: "x86_64-linux-musl-gcc",
CC_x86_64_unknown_linux_musl: "x86_64-linux-musl-gcc",
}
: {};
: "darwin" === platform
? {
RUSTFLAGS:
(env["RUSTFLAGS"] || "") + " -Clinker=x86_64-linux-musl-gcc",
TARGET_CC: "x86_64-linux-musl-gcc",
CC_x86_64_unknown_linux_musl: "x86_64-linux-musl-gcc",
}
: {};
return {
...defaultEnv,
...platformEnv,
Expand All @@ -127,8 +125,11 @@ class RustPlugin {
localSourceDir(funcArgs, profile, platform) {
let executable = "target";
if (MUSL_PLATFORMS.includes(platform)) {
let target = (funcArgs || {}).target || this.custom.target
executable = path.join(executable, target ? target : "x86_64-unknown-linux-musl");
let target = (funcArgs || {}).target || this.custom.target;
executable = path.join(
executable,
target ? target : "x86_64-unknown-linux-musl"
);
}
return path.join(executable, profile !== "dev" ? "release" : "debug");
}
Expand Down Expand Up @@ -281,6 +282,7 @@ class RustPlugin {

/** the entry point for building functions */
build() {
const strictMode = this.custom.strictMode !== false;
const service = this.serverless.service;
if (service.provider.name != "aws") {
return;
Expand All @@ -289,51 +291,61 @@ class RustPlugin {
this.functions().forEach((funcName) => {
const func = service.getFunction(funcName);
const runtime = func.runtime || service.provider.runtime;
if (runtime != RUST_RUNTIME) {

func.tags = func.tags || {};
if (!(runtime === RUST_RUNTIME || func.tags.language === "rust")) {
// skip functions which don't apply to rust
return;
}
rustFunctionsFound = true;
const { cargoPackage, binary } = this.cargoBinary(func);

this.serverless.cli.log(`Building Rust ${func.handler} func...`);
let profile = (func.rust || {}).profile || this.custom.profile;

const res = this.buildLocally(func)
? this.localBuild(func.rust, cargoPackage, binary, profile)
: this.dockerBuild(func.rust, cargoPackage, binary, profile);
if (res.error || res.status > 0) {
func.package = func.package || {};
if (func.package.artifact && func.package.artifact !== "") {
this.serverless.cli.log(
`Rust build encountered an error: ${res.error} ${res.status}.`
`Artifact defined for ${func.handler}, skipping build...`
);
throw new Error(res.error);
}
// If all went well, we should now have find a packaged compiled binary under `target/lambda/release`.
//
// The AWS "provided" lambda runtime requires executables to be named
// "bootstrap" -- https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html
//
// To avoid artifact naming conflicts when we potentially have more than one function
// we leverage the ability to declare a package artifact directly
// see https://serverless.com/framework/docs/providers/aws/guide/packaging/
// for more information
const artifactPath = path.join(
this.srcPath,
`target/lambda/${"dev" === profile ? "debug" : "release"}`,
`${binary}.zip`
);
func.package = func.package || {};
func.package.artifact = artifactPath;
} else {
const { cargoPackage, binary } = this.cargoBinary(func);

this.serverless.cli.log(`Building Rust ${func.handler} func...`);
let profile = (func.rust || {}).profile || this.custom.profile;

const res = this.buildLocally(func)
? this.localBuild(func.rust, cargoPackage, binary, profile)
: this.dockerBuild(func.rust, cargoPackage, binary, profile);
if (res.error || res.status > 0) {
this.serverless.cli.log(
`Rust build encountered an error: ${res.error} ${res.status}.`
);
throw new Error(res.error);
}
// If all went well, we should now have find a packaged compiled binary under `target/lambda/release`.
//
// The AWS "provided" lambda runtime requires executables to be named
// "bootstrap" -- https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html
//
// To avoid artifact naming conflicts when we potentially have more than one function
// we leverage the ability to declare a package artifact directly
// see https://serverless.com/framework/docs/providers/aws/guide/packaging/
// for more information
const artifactPath = path.join(
this.srcPath,
`target/lambda/${"dev" === profile ? "debug" : "release"}`,
`${binary}.zip`
);
func.package = func.package || {};
func.package.artifact = artifactPath;

// Ensure the runtime is set to a sane value for other plugins
if (func.runtime == RUST_RUNTIME) {
func.runtime = BASE_RUNTIME;
// Ensure the runtime is set to a sane value for other plugins
if (func.runtime == RUST_RUNTIME) {
func.runtime = BASE_RUNTIME;
}
}
});
if (service.provider.runtime === RUST_RUNTIME) {
service.provider.runtime = BASE_RUNTIME;
}
if (!rustFunctionsFound) {
if (!rustFunctionsFound && strictMode) {
throw new Error(
`Error: no Rust functions found. ` +
`Use 'runtime: ${RUST_RUNTIME}' in global or ` +
Expand Down
26 changes: 17 additions & 9 deletions tests/unit/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe("RustPlugin", () => {
dockerImage: "notsoftprops/lambda-rust",
dockerTag: "latest",
dockerless: true,
strictMode: true,
},
},
package: {},
Expand Down Expand Up @@ -40,6 +41,7 @@ describe("RustPlugin", () => {
dockerImage: "softprops/lambda-rust",
dockerTag: "latest",
dockerless: false,
strictMode: true,
});
});

Expand All @@ -54,6 +56,7 @@ describe("RustPlugin", () => {
dockerImage: "notsoftprops/lambda-rust",
dockerTag: "custom-tag",
dockerless: true,
strictMode: false,
},
},
package: {},
Expand All @@ -67,6 +70,7 @@ describe("RustPlugin", () => {
dockerImage: "notsoftprops/lambda-rust",
dockerTag: "custom-tag",
dockerless: true,
strictMode: false,
});
});

Expand Down Expand Up @@ -128,9 +132,13 @@ describe("RustPlugin", () => {
});

it("configures expected localBuildEnv", () => {
assert.deepEqual(plugin.localBuildEnv({}, "linux"), {}, "failed on linux");
assert.deepEqual(
plugin.localBuildEnv({}, "darwin"),
plugin.localBuildEnv({}, {}, "linux"),
{},
"failed on linux"
);
assert.deepEqual(
plugin.localBuildEnv({}, {}, "darwin"),

{
CC_x86_64_unknown_linux_musl: "x86_64-linux-musl-gcc",
Expand All @@ -140,7 +148,7 @@ describe("RustPlugin", () => {
"failed on osx"
);
assert.deepEqual(
plugin.localBuildEnv({}, "win32"),
plugin.localBuildEnv({}, {}, "win32"),
{
CC_x86_64_unknown_linux_musl: "rust-lld",
RUSTFLAGS: " -Clinker=rust-lld",
Expand All @@ -152,32 +160,32 @@ describe("RustPlugin", () => {

it("configures expected localSourceDir", () => {
assert.equal(
plugin.localSourceDir("dev", "linux"),
plugin.localSourceDir({}, "dev", "linux"),
path.join("target", "x86_64-unknown-linux-musl", "debug"),
"failed on linux"
);
assert.equal(
plugin.localSourceDir("release", "linux"),
plugin.localSourceDir({}, "release", "linux"),
path.join("target", "x86_64-unknown-linux-musl", "release"),
"failed on linux"
);
assert.equal(
plugin.localSourceDir("dev", "darwin"),
plugin.localSourceDir({}, "dev", "darwin"),
path.join("target", "x86_64-unknown-linux-musl", "debug"),
"failed on osx"
);
assert.equal(
plugin.localSourceDir("release", "darwin"),
plugin.localSourceDir({}, "release", "darwin"),
path.join("target", "x86_64-unknown-linux-musl", "release"),
"failed on osx"
);
assert.equal(
plugin.localSourceDir("dev", "win32"),
plugin.localSourceDir({}, "dev", "win32"),
path.join("target", "x86_64-unknown-linux-musl", "debug"),
"failed on windows"
);
assert.equal(
plugin.localSourceDir("release", "win32"),
plugin.localSourceDir({}, "release", "win32"),
path.join("target", "x86_64-unknown-linux-musl", "release"),
"failed on windows"
);
Expand Down