Skip to content

Commit

Permalink
Update lockfile function exception
Browse files Browse the repository at this point in the history
Add new exception for this function to handle any syntax errors or missing data within the lockfile

Related: #18455
PiperOrigin-RevId: 538144339
Change-Id: I82160f3bff6598c26b3f99c824fe85ea86086c1f
  • Loading branch information
SalmaSamy committed Jul 10, 2023
1 parent 273d3f7 commit f88921f
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.bazel.bzlmod.BazelDepGraphFunction.BazelDepGraphFunctionException;
import com.google.devtools.build.lib.bazel.repository.RepositoryOptions.LockfileMode;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.server.FailureDetails.ExternalDeps.Code;
Expand All @@ -35,7 +34,7 @@
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -81,8 +80,14 @@ public SkyValue compute(SkyKey skyKey, Environment env)
bazelLockFileValue = LOCKFILE_GSON.fromJson(json, BazelLockFileValue.class);
} catch (FileNotFoundException e) {
bazelLockFileValue = EMPTY_LOCKFILE;
} catch (IOException ex) {
throw new JsonIOException("Failed to read or parse module-lock file", ex);
} catch (IOException | JsonSyntaxException | NullPointerException e) {
throw new BazelLockfileFunctionException(
ExternalDepsException.withMessage(
Code.BAD_MODULE,
"Failed to read and parse the MODULE.bazel.lock file with error: %s."
+ " Try deleting it and rerun the build.",
e.getMessage()),
Transience.PERSISTENT);
}
return bazelLockFileValue;
}
Expand All @@ -99,7 +104,7 @@ public static void updateLockedModule(
BzlmodFlagsAndEnvVars flags,
ImmutableMap<String, String> localOverrideHashes,
ImmutableMap<ModuleKey, Module> resolvedDepGraph)
throws BazelDepGraphFunctionException {
throws BazelLockfileFunctionException {
RootedPath lockfilePath =
RootedPath.toRootedPath(Root.fromPath(rootDirectory), LabelConstants.MODULE_LOCKFILE_NAME);

Expand All @@ -113,10 +118,17 @@ public static void updateLockedModule(
try {
FileSystemUtils.writeContent(lockfilePath.asPath(), UTF_8, LOCKFILE_GSON.toJson(value));
} catch (IOException e) {
throw new BazelDepGraphFunctionException(
throw new BazelLockfileFunctionException(
ExternalDepsException.withCauseAndMessage(
Code.BAD_MODULE, e, "Unable to update module-lock file"),
Code.BAD_MODULE, e, "Unable to update the MODULE.bazel.lock file"),
Transience.PERSISTENT);
}
}

static final class BazelLockfileFunctionException extends SkyFunctionException {

BazelLockfileFunctionException(Exception cause, Transience transience) {
super(cause, transience);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -387,6 +389,136 @@ public void fullModule() throws Exception {
assertThat(value.getModuleDepGraph()).isEqualTo(depGraph);
}

@Test
public void invalidLockfileEmptyFile() throws Exception {
scratch.file(
rootDirectory.getRelative("MODULE.bazel").getPathString(),
"module(name='my_root', version='1.0')");

EvaluationResult<RootModuleFileValue> rootResult =
evaluator.evaluate(
ImmutableList.of(ModuleFileValue.KEY_FOR_ROOT_MODULE), evaluationContext);
if (rootResult.hasError()) {
fail(rootResult.getError().toString());
}
RootModuleFileValue rootValue = rootResult.get(ModuleFileValue.KEY_FOR_ROOT_MODULE);

ImmutableMap<ModuleKey, Module> depGraph =
ImmutableMap.of(
ModuleKey.ROOT,
BazelModuleResolutionFunction.moduleFromInterimModule(
rootValue.getModule(), null, null));

UpdateLockFileKey key =
UpdateLockFileKey.create("moduleHash", depGraph, rootValue.getOverrides());
EvaluationResult<BazelLockFileValue> result =
evaluator.evaluate(ImmutableList.of(key), evaluationContext);
if (result.hasError()) {
fail(result.getError().toString());
}

scratch.overwriteFile(rootDirectory.getRelative("MODULE.bazel.lock").getPathString(), "{}");

result = evaluator.evaluate(ImmutableList.of(BazelLockFileValue.KEY), evaluationContext);
if (!result.hasError()) {
fail("expected error about missing field in the lockfile, but succeeded");
}
assertThat(result.getError().toString())
.contains(
"Failed to read and parse the MODULE.bazel.lock file with error: Null moduleFileHash."
+ " Try deleting it and rerun the build.");
}

@Test
public void invalidLockfileNullFlag() throws Exception {
scratch.file(
rootDirectory.getRelative("MODULE.bazel").getPathString(),
"module(name='my_root', version='1.0')");

EvaluationResult<RootModuleFileValue> rootResult =
evaluator.evaluate(
ImmutableList.of(ModuleFileValue.KEY_FOR_ROOT_MODULE), evaluationContext);
if (rootResult.hasError()) {
fail(rootResult.getError().toString());
}
RootModuleFileValue rootValue = rootResult.get(ModuleFileValue.KEY_FOR_ROOT_MODULE);

ImmutableMap<ModuleKey, Module> depGraph =
ImmutableMap.of(
ModuleKey.ROOT,
BazelModuleResolutionFunction.moduleFromInterimModule(
rootValue.getModule(), null, null));

UpdateLockFileKey key =
UpdateLockFileKey.create("moduleHash", depGraph, rootValue.getOverrides());
EvaluationResult<BazelLockFileValue> result =
evaluator.evaluate(ImmutableList.of(key), evaluationContext);
if (result.hasError()) {
fail(result.getError().toString());
}

JsonObject jsonObject =
(JsonObject) JsonParser.parseString(scratch.readFile("MODULE.bazel.lock"));
jsonObject.get("flags").getAsJsonObject().remove("directDependenciesMode");
scratch.overwriteFile(
rootDirectory.getRelative("MODULE.bazel.lock").getPathString(), jsonObject.toString());

result = evaluator.evaluate(ImmutableList.of(BazelLockFileValue.KEY), evaluationContext);
if (!result.hasError()) {
fail("expected error about missing field in the lockfile, but succeeded");
}
assertThat(result.getError().toString())
.contains(
"Failed to read and parse the MODULE.bazel.lock file with error: Null"
+ " directDependenciesMode. Try deleting it and rerun the build.");
}

@Test
public void invalidLockfileMalformed() throws Exception {
scratch.file(
rootDirectory.getRelative("MODULE.bazel").getPathString(),
"module(name='my_root', version='1.0')");

EvaluationResult<RootModuleFileValue> rootResult =
evaluator.evaluate(
ImmutableList.of(ModuleFileValue.KEY_FOR_ROOT_MODULE), evaluationContext);
if (rootResult.hasError()) {
fail(rootResult.getError().toString());
}
RootModuleFileValue rootValue = rootResult.get(ModuleFileValue.KEY_FOR_ROOT_MODULE);

ImmutableMap<ModuleKey, Module> depGraph =
ImmutableMap.of(
ModuleKey.ROOT,
BazelModuleResolutionFunction.moduleFromInterimModule(
rootValue.getModule(), null, null));

UpdateLockFileKey key =
UpdateLockFileKey.create("moduleHash", depGraph, rootValue.getOverrides());
EvaluationResult<BazelLockFileValue> result =
evaluator.evaluate(ImmutableList.of(key), evaluationContext);
if (result.hasError()) {
fail(result.getError().toString());
}

JsonObject jsonObject =
(JsonObject) JsonParser.parseString(scratch.readFile("MODULE.bazel.lock"));
jsonObject.get("flags").getAsJsonObject().addProperty("allowedYankedVersions", "string!");
scratch.overwriteFile(
rootDirectory.getRelative("MODULE.bazel.lock").getPathString(), jsonObject.toString());

result = evaluator.evaluate(ImmutableList.of(BazelLockFileValue.KEY), evaluationContext);
if (!result.hasError()) {
fail("expected error about invalid field value in the lockfile, but succeeded");
}
assertThat(result.getError().toString())
.contains(
"Failed to read and parse the MODULE.bazel.lock file with error:"
+ " java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1"
+ " column 129 path $.flags.allowedYankedVersions. Try deleting it and rerun the"
+ " build.");
}

@AutoValue
abstract static class UpdateLockFileKey implements SkyKey {

Expand Down

0 comments on commit f88921f

Please sign in to comment.