Skip to content

Commit

Permalink
Allows for controlling with attributes are ignored during rule hashing (
Browse files Browse the repository at this point in the history
#182)

* WIP: Ignore location attribute

Related Different workspaces produce different hashes #180

* properly inject argument

* get tests running
  • Loading branch information
tinder-maxwellelliott authored Jun 9, 2023
1 parent e226c1c commit 6752eff
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 21 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ workspace.
individual third party dependency change won't
invalidate all targets in the mono repo.
-h, --help Show this help message and exit.
--ignoredRuleHashingAttributes=<ignoredRuleHashingAttributes>
Attributes that should be ignored when hashing rule
targets.
-k, --[no-]keep_going This flag controls if `bazel query` will be executed
with the `--keep_going` flag or not. Disabling this
flag allows you to catch configuration issues in
Expand Down
8 changes: 4 additions & 4 deletions cli/src/main/kotlin/com/bazel_diff/bazel/BazelRule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import com.google.devtools.build.lib.query2.proto.proto2api.Build
// Ignore generator_location when computing a target's hash since it is likely to change and does not
// affect a target's generated actions. Internally, Bazel also does this when computing a target's hash:
// https://github.com/bazelbuild/bazel/blob/6971b016f1e258e3bb567a0f9fe7a88ad565d8f2/src/main/java/com/google/devtools/build/lib/query2/query/output/SyntheticAttributeHashCalculator.java#L78-L81
private val IGNORED_ATTRS = arrayOf("generator_location")
private val DEFAULT_IGNORED_ATTRS = arrayOf("generator_location")

class BazelRule(private val rule: Build.Rule) {
val digest: ByteArray by lazy {
sha256 {
fun digest(ignoredAttrs: Set<String>): ByteArray {
return sha256 {
safePutBytes(rule.ruleClassBytes.toByteArray())
safePutBytes(rule.nameBytes.toByteArray())
safePutBytes(rule.skylarkEnvironmentHashCodeBytes.toByteArray())
for (attribute in rule.attributeList) {
if (!IGNORED_ATTRS.contains(attribute.name))
if (!DEFAULT_IGNORED_ATTRS.contains(attribute.name) && !ignoredAttrs.contains(attribute.name))
safePutBytes(attribute.toByteArray())
}
}
Expand Down
10 changes: 9 additions & 1 deletion cli/src/main/kotlin/com/bazel_diff/cli/GenerateHashesCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ class GenerateHashesCommand : Callable<Int> {
)
var outputPath: File? = null

@CommandLine.Option(
names = ["--ignoredRuleHashingAttributes"],
description = ["Attributes that should be ignored when hashing rule targets."],
scope = CommandLine.ScopeType.INHERIT,
converter = [OptionsConverter::class],
)
var ignoredRuleHashingAttributes: Set<String> = emptySet()

@CommandLine.Spec
lateinit var spec: CommandLine.Model.CommandSpec

Expand All @@ -134,7 +142,7 @@ class GenerateHashesCommand : Callable<Int> {
)
}

return when (GenerateHashesInteractor().execute(seedFilepaths, outputPath)) {
return when (GenerateHashesInteractor().execute(seedFilepaths, outputPath, ignoredRuleHashingAttributes)) {
true -> CommandLine.ExitCode.OK
false -> CommandLine.ExitCode.SOFTWARE
}.also { stopKoin() }
Expand Down
18 changes: 14 additions & 4 deletions cli/src/main/kotlin/com/bazel_diff/hash/BuildGraphHasher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ class BuildGraphHasher(private val bazelClient: BazelClient) : KoinComponent {
private val sourceFileHasher: SourceFileHasher by inject()
private val logger: Logger by inject()

fun hashAllBazelTargetsAndSourcefiles(seedFilepaths: Set<Path> = emptySet()): Map<String, String> {
fun hashAllBazelTargetsAndSourcefiles(
seedFilepaths: Set<Path> = emptySet(),
ignoredAttrs: Set<String> = emptySet()
): Map<String, String> {
/**
* Bazel will lock parallel queries but this is still allowing us to hash source files while executing a parallel query
*/
Expand Down Expand Up @@ -56,7 +59,12 @@ class BuildGraphHasher(private val bazelClient: BazelClient) : KoinComponent {
Pair(sourceDigestsFuture.await(), targetsTask.await())
}
val seedForFilepaths = createSeedForFilepaths(seedFilepaths)
return hashAllTargets(seedForFilepaths, sourceDigests, allTargets)
return hashAllTargets(
seedForFilepaths,
sourceDigests,
allTargets,
ignoredAttrs
)
}

private fun hashSourcefiles(targets: List<Build.Target>): ConcurrentMap<String, ByteArray> {
Expand Down Expand Up @@ -94,7 +102,8 @@ class BuildGraphHasher(private val bazelClient: BazelClient) : KoinComponent {
private fun hashAllTargets(
seedHash: ByteArray,
sourceDigests: ConcurrentMap<String, ByteArray>,
allTargets: List<BazelTarget>
allTargets: List<BazelTarget>,
ignoredAttrs: Set<String>
): Map<String, String> {
val ruleHashes: ConcurrentMap<String, ByteArray> = ConcurrentHashMap()
val targetToRule: MutableMap<String, BazelRule> = HashMap()
Expand All @@ -107,7 +116,8 @@ class BuildGraphHasher(private val bazelClient: BazelClient) : KoinComponent {
targetToRule,
sourceDigests,
ruleHashes,
seedHash
seedHash,
ignoredAttrs
)
Pair(target.name, targetDigest.toHexString())
}
Expand Down
6 changes: 4 additions & 2 deletions cli/src/main/kotlin/com/bazel_diff/hash/RuleHasher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class RuleHasher(private val useCquery: Boolean, private val fineGrainedHashExte
ruleHashes: ConcurrentMap<String, ByteArray>,
sourceDigests: ConcurrentMap<String, ByteArray>,
seedHash: ByteArray?,
depPath: LinkedHashSet<String>?
depPath: LinkedHashSet<String>?,
ignoredAttrs: Set<String>
): ByteArray {
val depPathClone = if (depPath != null) LinkedHashSet(depPath) else LinkedHashSet()
if (depPathClone.contains(rule.name)) {
Expand All @@ -40,7 +41,7 @@ class RuleHasher(private val useCquery: Boolean, private val fineGrainedHashExte
ruleHashes[rule.name]?.let { return it }

val finalHashValue = sha256 {
safePutBytes(rule.digest)
safePutBytes(rule.digest(ignoredAttrs))
safePutBytes(seedHash)

for (ruleInput in rule.ruleInputList(useCquery, fineGrainedHashExternalRepos)) {
Expand All @@ -60,6 +61,7 @@ class RuleHasher(private val useCquery: Boolean, private val fineGrainedHashExte
sourceDigests,
seedHash,
depPathClone,
ignoredAttrs
)
safePutBytes(ruleInputHash)
}
Expand Down
16 changes: 13 additions & 3 deletions cli/src/main/kotlin/com/bazel_diff/hash/TargetHasher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class TargetHasher : KoinComponent {
allRulesMap: Map<String, BazelRule>,
sourceDigests: ConcurrentMap<String, ByteArray>,
ruleHashes: ConcurrentMap<String, ByteArray>,
seedHash: ByteArray?
seedHash: ByteArray?,
ignoredAttrs: Set<String>
): ByteArray {
return when (target) {
is BazelTarget.GeneratedFile -> {
Expand All @@ -30,12 +31,21 @@ class TargetHasher : KoinComponent {
ruleHashes,
sourceDigests,
seedHash,
depPath = null
depPath = null,
ignoredAttrs
)
}
}
is BazelTarget.Rule -> {
ruleHasher.digest(target.rule, allRulesMap, ruleHashes, sourceDigests, seedHash, depPath = null)
ruleHasher.digest(
target.rule,
allRulesMap,
ruleHashes,
sourceDigests,
seedHash,
depPath = null,
ignoredAttrs
)
}
is BazelTarget.SourceFile -> sha256 {
safePutBytes(sourceDigests[target.sourceFileName])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class GenerateHashesInteractor : KoinComponent {
private val logger: Logger by inject()
private val gson: Gson by inject()

fun execute(seedFilepaths: File?, outputPath: File?): Boolean {
fun execute(seedFilepaths: File?, outputPath: File?, ignoredRuleHashingAttributes: Set<String>): Boolean {
return try {
val epoch = Calendar.getInstance().getTimeInMillis()
var seedFilepathsSet: Set<Path> = when {
Expand All @@ -31,7 +31,10 @@ class GenerateHashesInteractor : KoinComponent {
}
else -> emptySet()
}
val hashes = buildGraphHasher.hashAllBazelTargetsAndSourcefiles(seedFilepathsSet)
val hashes = buildGraphHasher.hashAllBazelTargetsAndSourcefiles(
seedFilepathsSet,
ignoredRuleHashingAttributes
)
when (outputPath) {
null -> FileWriter(FileDescriptor.out)
else -> FileWriter(outputPath)
Expand Down
6 changes: 3 additions & 3 deletions cli/src/test/kotlin/com/bazel_diff/bazel/BazelRuleTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class BazelRuleTest {
.setRuleClass("java_library")
.setName("libbar")
.build()
assertThat(BazelRule(rule1Pb).digest).isNotEqualTo(BazelRule(rule2Pb).digest)
assertThat(BazelRule(rule1Pb).digest(emptySet())).isNotEqualTo(BazelRule(rule2Pb).digest(emptySet()))
}
@Test
fun testIgnoreAttributes() {
Expand All @@ -41,6 +41,6 @@ class BazelRuleTest {
.setStringValue("path/to/BUILD:111:1").build())
.build()

assertThat(BazelRule(rule1Pb).digest).isEqualTo(BazelRule(rule2Pb).digest)
assertThat(BazelRule(rule1Pb).digest(emptySet())).isEqualTo(BazelRule(rule2Pb).digest(emptySet()))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class BuildGraphHasherTest : KoinTest {
assertThat(hash).hasSize(3)
val oldHash = hash["rule3"]!!

whenever(generator.rule.digest).thenReturn("newDigest".toByteArray())
whenever(generator.rule.digest(emptySet())).thenReturn("newDigest".toByteArray())
hash = hasher.hashAllBazelTargetsAndSourcefiles()
assertThat(hash).hasSize(3)
val newHash = hash["rule3"]!!
Expand All @@ -175,7 +175,7 @@ class BuildGraphHasherTest : KoinTest {
val rule = mock<BazelRule>()
whenever(rule.name).thenReturn(name)
whenever(rule.ruleInputList(false, emptySet())).thenReturn(inputs)
whenever(rule.digest).thenReturn(digest.toByteArray())
whenever(rule.digest(emptySet())).thenReturn(digest.toByteArray())
whenever(target.rule).thenReturn(rule)
whenever(target.name).thenReturn(name)
return target
Expand Down

0 comments on commit 6752eff

Please sign in to comment.