def test_nested_metadata_file_changes_are_ignored(self): """ lib/a1/src/... lib/a1/MVN-INF/... lib/a1/a2/src/... lib/a1/a2/MVN-INF/... Changes to files in lib/a1/a2/MVN-INF should be ignored by lib/a1's hash calculation. """ a1_package = "lib/a1" a2_package = "lib/a1/a2" repo_root_path = self._setup_repo_with_package(a1_package) self._touch_file_at_path(repo_root_path, a1_package, "MVN-INF", "BUILD.pom.released") self._touch_file_at_path(repo_root_path, a1_package, "", "some_file") self._touch_file_at_path(repo_root_path, a2_package, "MVN-INF", "BUILD.pom.released") self._touch_file_at_path(repo_root_path, a2_package, "", "some_file") self._commit(repo_root_path) a1_hash = git.get_dir_hash(repo_root_path, a1_package, exclusions.src_exclusions()) # modify file under a2 metadata - should be ignored self._touch_file_at_path(repo_root_path, a2_package, "MVN-INF", "BUILD.pom.released") self._commit(repo_root_path) updated_a1_hash = git.get_dir_hash(repo_root_path, a1_package, exclusions.src_exclusions()) self.assertEqual(a1_hash, updated_a1_hash)
def test_update_BUILD_pom_released__set_artifact_hash_to_current(self): pack1 = "somedir/p1" pack2 = "somedir/p2" repo_root = tempfile.mkdtemp("monorepo") pack1_path = os.path.join(repo_root, pack1) os.makedirs(os.path.join(pack1_path)) pack2_path = os.path.join(repo_root, pack2) os.makedirs(os.path.join(pack2_path)) self._write_build_pom_released(pack1_path, "1.0.0", "aaa") self._write_build_pom_released(pack2_path, "1.0.0", "bbb") self._setup_repo(repo_root) self._commit(repo_root) self._touch_file_at_path(repo_root, pack1, "blah1") self._commit(repo_root) pack1_hash = git.get_dir_hash(repo_root, pack1, exclusions.src_exclusions()) self._touch_file_at_path(repo_root, pack2, "blah2") self._commit(repo_root) pack2_hash = git.get_dir_hash(repo_root, pack2, exclusions.src_exclusions()) self.assertNotEqual(pack1_hash, pack2_hash) buildpomupdate.update_released_artifact(repo_root, [pack1, pack2], exclusions.src_exclusions(), use_current_artifact_hash=True) with open(os.path.join(pack1_path, "MVN-INF", "BUILD.pom.released"), "r") as f: content = f.read() self.assertIn('artifact_hash = "%s"' % pack1_hash, content) with open(os.path.join(pack2_path, "MVN-INF", "BUILD.pom.released"), "r") as f: content = f.read() self.assertIn('artifact_hash = "%s"' % pack2_hash, content)
def test_pom_released_changes_are_ignored(self): package = "a/b/c" repo_root_path = self._setup_repo_with_package(package) self._touch_file_at_path(repo_root_path, package, "MVN-INF", "pom.xml.released") self._touch_file_at_path(repo_root_path, package, "", "some_file") self._commit(repo_root_path) current_artifact_hash = git.get_dir_hash(repo_root_path, [package], exclusions.src_exclusions()) art_def = buildpom.MavenArtifactDef( "g1", "a1", "1.1.0", bazel_package=package, released_version="1.2.0", released_artifact_hash=current_artifact_hash) # update pom.xml.released and commit - that change should be ignored self._touch_file_at_path(repo_root_path, package, "MVN-INF", "pom.xml.released") self._commit(repo_root_path) art_def = artifactprocessor.augment_artifact_def( repo_root_path, art_def, exclusions.src_exclusions()) self.assertNotEqual(None, art_def.requires_release) self.assertFalse(art_def.requires_release)
def test_parse_src_dep_with_changes_since_last_release(self): """ Verifies that a source dependency label is correctly parsed into a Dependency instance. The source dependency has a BUILD.pom.released file that indicates that changes have been made since the last release; therefore the dependency instance should point to the monorepo source artifact. """ version = "1.2.3" released_version = "1.2.0" package_name = "package1" group_id = "group1" artifact_id = "art1" repo_root = tempfile.mkdtemp("monorepo") self._touch_file_at_path(repo_root, "", "MVN-INF", "LIBRARY.root") self._write_build_pom(repo_root, package_name, artifact_id, group_id, version) self._setup_repo(repo_root) package_hash = git.get_dir_hash(repo_root, [package_name], exclusions.src_exclusions()) self._write_build_pom_released(repo_root, package_name, released_version, package_hash) self._touch_file_at_path(repo_root, package_name, "", "myfile") self._commit(repo_root) ws = workspace.Workspace(repo_root, [], exclusions.src_exclusions(), maveninstallinfo.NOOP, pom_content=pomcontent.NOOP) deps = ws.parse_dep_labels(["//%s" % package_name]) self.assertEqual(1, len(deps)) self.assertEqual(group_id, deps[0].group_id) self.assertEqual(artifact_id, deps[0].artifact_id) self.assertFalse(deps[0].external) self.assertEqual(version, deps[0].version) self.assertEqual(package_name, deps[0].bazel_package)
def test_artifact_with_changes_since_last_release__local_edits(self): """ We added uncommitted change detection to improve the local developer experience: any artifact that has uncommitted changes should get marked as needing to be released. """ package = "pack1/pack2" repo_root_path = self._setup_repo_with_package(package) current_artifact_hash = git.get_dir_hash(repo_root_path, [package], exclusions.src_exclusions()) art_def = buildpom.MavenArtifactDef( "g1", "a1", "1.1.0", released_version="1.2.0", bazel_package=package, released_artifact_hash=current_artifact_hash) # add a new file ... self._touch_file_at_path(repo_root_path, package, "", "Foo.java") # ... but DON't commit art_def = artifactprocessor.augment_artifact_def( repo_root_path, art_def, exclusions.src_exclusions()) self.assertNotEqual(None, art_def.requires_release) self.assertTrue(art_def.requires_release, "Expected artifact to require release") self.assertIs(releasereason.ReleaseReason.UNCOMMITTED_CHANGES, art_def.release_reason)
def test_additional_change_detected_packages__not_set(self): package1 = "path/pack1" # change detected (by default) package2 = "path/pack2" # ignored repo_root_path = self._setup_repo_with_package(package1) self._add_package(repo_root_path, package2) self._touch_file_at_path(repo_root_path, package1, "", "Blah.java") self._touch_file_at_path(repo_root_path, package2, "", "Blah.java") self._commit(repo_root_path) current_artifact_hash = git.get_dir_hash(repo_root_path, [package1], exclusions.src_exclusions()) art_def = buildpom.MavenArtifactDef( "g1", "a1", "1.1.0", released_version="1.2.0", bazel_package=package1, released_artifact_hash=current_artifact_hash) # modify an existing file in package2 - since we are not explicitly # detecting changes in it, it shouldn't matter: self._touch_file_at_path(repo_root_path, package2, "", "Blah.java") self._commit(repo_root_path) art_def = artifactprocessor.augment_artifact_def( repo_root_path, art_def, exclusions.src_exclusions()) self.assertNotEqual(None, art_def.requires_release) self.assertFalse(art_def.requires_release, "Artifact should not be released")
def test_artifact_with_changes_since_last_release__modified_file(self): package = "pack1/pack2" repo_root_path = self._setup_repo_with_package(package) self._touch_file_at_path(repo_root_path, package, "", "Blah.java") self._commit(repo_root_path) current_artifact_hash = git.get_dir_hash(repo_root_path, [package], exclusions.src_exclusions()) art_def = buildpom.MavenArtifactDef( "g1", "a1", "1.1.0", released_version="1.2.0", bazel_package=package, released_artifact_hash=current_artifact_hash) # modify an existing file: self._touch_file_at_path(repo_root_path, package, "", "Blah.java") self._commit(repo_root_path) art_def = artifactprocessor.augment_artifact_def( repo_root_path, art_def, exclusions.src_exclusions()) self.assertNotEqual(None, art_def.requires_release) self.assertTrue(art_def.requires_release, "Expected artifact to require release") self.assertIs(releasereason.ReleaseReason.ARTIFACT, art_def.release_reason)
def test_one_lib_changed__lib_b__pom_changes_only(self): """ B a2's pom changed since it was last released. """ self._write_file( self.repo_root_path, "libs/b/a2", "MVN-INF", "pom.xml.released", """<project> <dependencies> ... </dependencies> </project>""") self._write_file(self.repo_root_path, "libs/b/a2", "MVN-INF", POM_TEMPLATE_FILE, "<project></project>") self._commit(self.repo_root_path) released_artifact_hash = git.get_dir_hash(self.repo_root_path, ["libs/b/a2"], exclusions.src_exclusions()) self._write_build_pom_released(self.repo_root_path, "libs/b/a2", "1.0.0", released_artifact_hash) result = self.crawler.crawl(["libs/a/a1"]) self.assertEqual( set(["libs/a/a1", "libs/a/a2", "libs/b/a1", "libs/b/a2"]), set([p.artifact_def.bazel_package for p in result.pomgens])) node_a_a1 = result.nodes[0] self.assertIs(node_a_a1.artifact_def.release_reason, rr.ReleaseReason.TRANSITIVE) node_b_a1 = node_a_a1.children[0] self.assertEqual("libs/b/a1", node_b_a1.artifact_def.bazel_package) self.assertIs(node_b_a1.artifact_def.release_reason, rr.ReleaseReason.POM)
def test_dot_gitignore_changes_are_ignored(self): src_exclusions = exclusions.src_exclusions(file_names=(".gitignore", )) package = "a/b/c" repo_root_path = self._setup_repo_with_package(package) self._touch_file_at_path(repo_root_path, package, "MVN-INF", "BUILD.pom") self._touch_file_at_path(repo_root_path, package, "f", ".gitignore") self._commit(repo_root_path) current_artifact_hash = git.get_dir_hash(repo_root_path, [package], src_exclusions) art_def = buildpom.MavenArtifactDef( "g1", "a1", "1.1.0", bazel_package=package, released_version="1.2.0", released_artifact_hash=current_artifact_hash) # update .md file - that change should be ignored self._touch_file_at_path(repo_root_path, package, "f", ".gitignore") self._commit(repo_root_path) art_def = artifactprocessor.augment_artifact_def( repo_root_path, art_def, src_exclusions) self.assertNotEqual(None, art_def.requires_release) self.assertFalse(art_def.requires_release)
def _has_changed_since_last_release(repo_root_path, art_def, source_exclusions): current_artifact_hash = git.get_dir_hash(repo_root_path, art_def.bazel_package, source_exclusions) assert current_artifact_hash is not None return current_artifact_hash != art_def.released_artifact_hash
def update_released_artifact(root_path, packages, source_exclusions, new_version=None, new_artifact_hash=None, use_current_artifact_hash=False): """ Updates the version and/or artifact hash attributes in the BUILD.pom.released files in the specified packages. Creates the BUILD.pom.released file if it does not exist. """ for package in packages: path = os.path.join(root_path, package, "BUILD.pom.released") try: if use_current_artifact_hash: assert new_artifact_hash is None # we need to load the BUILD.pom file to see whether additional # packages are specified packages = [package] art_def = buildpom.parse_maven_artifact_def(root_path, package) if art_def is not None: # if the BUILD.pom file doesn't exist, then by definition # additional packages cannot have been specified packages += art_def.additional_change_detected_packages artifact_hash = git.get_dir_hash(root_path, packages, source_exclusions) assert artifact_hash is not None else: artifact_hash = new_artifact_hash content, _ = mdfiles.read_file( root_path, package, mdfiles.BUILD_POM_RELEASED_FILE_NAME) if content is not None: if new_version is not None: content = _update_version_in_build_pom_released_content( content, new_version) if artifact_hash is not None: content = _update_artifact_hash_in_build_pom_released_content( content, artifact_hash) mdfiles.write_file(content, root_path, package, mdfiles.BUILD_POM_RELEASED_FILE_NAME) else: if not os.path.exists(os.path.join(root_path, package)): raise Exception("Bad package %s" % package) content = _get_build_pom_released_content( new_version, artifact_hash) mdfiles.write_file(content, root_path, package, mdfiles.BUILD_POM_RELEASED_FILE_NAME) except: print("[ERROR] Cannot update BUILD.pom.released [%s]: %s" % (path, sys.exc_info())) raise
def test_artifact_without_changes_since_last_release(self): repo_root_path = self._setup_repo_with_package("pack1/pack2") current_artifact_hash = git.get_dir_hash(repo_root_path, "pack1/pack2", exclusions.src_exclusions()) art_def = buildpom.MavenArtifactDef("g1", "a1", "1.1.0", bazel_package="pack1/pack2", released_version="1.2.0", released_artifact_hash=current_artifact_hash) art_def = artifactprocessor.augment_artifact_def(repo_root_path, art_def, exclusions.src_exclusions()) self.assertNotEqual(None, art_def.requires_release) self.assertFalse(art_def.requires_release) self.assertEqual(None, art_def.release_reason)
def _has_changed_since_last_release(repo_root_path, art_def, source_exclusions): all_packages = [art_def.bazel_package ] + art_def.additional_change_detected_packages current_artifact_hash = git.get_dir_hash(repo_root_path, all_packages, source_exclusions) assert current_artifact_hash is not None return current_artifact_hash != art_def.released_artifact_hash
def _write_all_build_pom_released(self, repo_root_path): # LIB A dir_hash = git.get_dir_hash(repo_root_path, ["libs/a/a1"], exclusions.src_exclusions()) self._write_build_pom_released(repo_root_path, "libs/a/a1", "0.0.1", dir_hash) dir_hash = git.get_dir_hash(repo_root_path, ["libs/a/a2"], exclusions.src_exclusions()) self._write_build_pom_released(repo_root_path, "libs/a/a2", "0.0.1", dir_hash) # LIB B dir_hash = git.get_dir_hash(repo_root_path, ["libs/b/a1"], exclusions.src_exclusions()) self._write_build_pom_released(repo_root_path, "libs/b/a1", "0.0.2", dir_hash) dir_hash = git.get_dir_hash(repo_root_path, ["libs/b/a2"], exclusions.src_exclusions()) self._write_build_pom_released(repo_root_path, "libs/b/a2", "0.0.2", dir_hash) # LIB C dir_hash = git.get_dir_hash(repo_root_path, ["libs/c/a1"], exclusions.src_exclusions()) self._write_build_pom_released(repo_root_path, "libs/c/a1", "0.0.3", dir_hash) dir_hash = git.get_dir_hash(repo_root_path, ["libs/c/a2"], exclusions.src_exclusions()) self._write_build_pom_released(repo_root_path, "libs/c/a2", "0.0.3", dir_hash)
def update_released_artifact(root_path, packages, source_exclusions, new_version=None, new_artifact_hash=None, use_current_artifact_hash=False): """ Updates the version and/or artifact hash attributes in the BUILD.pom.released files in the specified packages. Creates the BUILD.pom.released file if it does not exist. """ for package in packages: path = os.path.join(root_path, package, "BUILD.pom.released") try: if use_current_artifact_hash: assert new_artifact_hash is None artifact_hash = git.get_dir_hash(root_path, package, source_exclusions) assert artifact_hash is not None else: artifact_hash = new_artifact_hash content, _ = mdfiles.read_file( root_path, package, mdfiles.BUILD_POM_RELEASED_FILE_NAME) if content is not None: if new_version is not None: content = _update_version_in_build_pom_released_content( content, new_version) if artifact_hash is not None: content = _update_artifact_hash_in_build_pom_released_content( content, artifact_hash) mdfiles.write_file(content, root_path, package, mdfiles.BUILD_POM_RELEASED_FILE_NAME) else: if not os.path.exists(os.path.join(root_path, package)): raise Exception("Bad package %s" % package) content = _get_build_pom_released_content( new_version, artifact_hash) mdfiles.write_file(content, root_path, package, mdfiles.BUILD_POM_RELEASED_FILE_NAME) except: print("[ERROR] Cannot update BUILD.pom.released [%s]: %s" % (path, sys.exc_info())) raise
def test_released_pom_exists_without_changes(self): """ B a1 has a pom.xml.released file, but it has not changed. """ self._write_file(self.repo_root_path, "libs/b/a1", "MVN-INF", "pom.xml.released", "<project></project>") self._write_file(self.repo_root_path, "libs/b/a1", "MVN-INF", POM_TEMPLATE_FILE, "<project></project>") self._commit(self.repo_root_path) released_artifact_hash = git.get_dir_hash(self.repo_root_path, ["libs/b/a1"], exclusions.src_exclusions()) self._write_build_pom_released(self.repo_root_path, "libs/b/a1", "1.0.0", released_artifact_hash) result = self.crawler.crawl(["libs/a/a1"]) self.assertEqual(0, len(result.pomgens))
def test_artifact_without_changes_always_release(self): repo_root_path = self._setup_repo_with_package("pack1/pack2") current_artifact_hash = git.get_dir_hash(repo_root_path, "pack1/pack2", exclusions.src_exclusions()) art_def = buildpom.MavenArtifactDef( "g1", "a1", "1.1.0", bazel_package="pack1/pack2", released_version="1.2.0", released_artifact_hash=current_artifact_hash, change_detection=False) art_def = artifactprocessor.augment_artifact_def( repo_root_path, art_def, exclusions.src_exclusions()) self.assertNotEqual(None, art_def.requires_release) self.assertTrue(art_def.requires_release, "Expected artifact to require release") self.assertEqual(releasereason.ReleaseReason.ALWAYS, art_def.release_reason)
def test_test_changes_are_ignored(self): """ We are assuming the de-facto Maven directory structure standard: src/main/... - prod code src/test/... - tests """ src_exclusions = exclusions.src_exclusions(relative_paths=("src/test",)) package = "pack" repo_root_path = self._setup_repo_with_package(package) self._touch_file_at_path(repo_root_path, package, "MVN-INF", "BUILD.pom.released") self._touch_file_at_path(repo_root_path, package, "src/main", "MyClass.java") self._touch_file_at_path(repo_root_path, package, "src/test", "MyTest.java") self._commit(repo_root_path) current_artifact_hash = git.get_dir_hash(repo_root_path, package, src_exclusions) art_def = buildpom.MavenArtifactDef("g1", "a1", "1.1.0", bazel_package=package, released_version="1.2.0", released_artifact_hash=current_artifact_hash) # update test class and commit - that change should be ignored self._touch_file_at_path(repo_root_path, package, "src/test", "MyTest.java") self._commit(repo_root_path) art_def = artifactprocessor.augment_artifact_def(repo_root_path, art_def, src_exclusions) self.assertNotEqual(None, art_def.requires_release) self.assertFalse(art_def.requires_release)