diff --git a/.github/workflows/getdeps_linux.yml b/.github/workflows/getdeps_linux.yml index 66897d923c4b..71fe13ad614b 100644 --- a/.github/workflows/getdeps_linux.yml +++ b/.github/workflows/getdeps_linux.yml @@ -15,7 +15,7 @@ permissions: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Show disk space at start @@ -36,6 +36,9 @@ jobs: - name: Fetch boost if: ${{ steps.paths.outputs.boost_SOURCE }} run: python3 build/fbcode_builder/getdeps.py --allow-system-packages fetch --no-tests boost + - name: Fetch bz2 + if: ${{ steps.paths.outputs.bz2_SOURCE }} + run: python3 build/fbcode_builder/getdeps.py --allow-system-packages fetch --no-tests bz2 - name: Fetch ninja if: ${{ steps.paths.outputs.ninja_SOURCE }} run: python3 build/fbcode_builder/getdeps.py --allow-system-packages fetch --no-tests ninja @@ -154,6 +157,22 @@ jobs: with: path: ${{ steps.paths.outputs.boost_INSTALL }} key: ${{ steps.paths.outputs.boost_CACHE_KEY }}-install + - name: Restore bz2 from cache + id: restore_bz2 + if: ${{ steps.paths.outputs.bz2_SOURCE }} + uses: actions/cache/restore@v4 + with: + path: ${{ steps.paths.outputs.bz2_INSTALL }} + key: ${{ steps.paths.outputs.bz2_CACHE_KEY }}-install + - name: Build bz2 + if: ${{ steps.paths.outputs.bz2_SOURCE && ! steps.restore_bz2.outputs.cache-hit }} + run: python3 build/fbcode_builder/getdeps.py --allow-system-packages build --free-up-disk --no-tests bz2 + - name: Save bz2 to cache + uses: actions/cache/save@v4 + if: ${{ steps.paths.outputs.bz2_SOURCE && ! steps.restore_bz2.outputs.cache-hit }} + with: + path: ${{ steps.paths.outputs.bz2_INSTALL }} + key: ${{ steps.paths.outputs.bz2_CACHE_KEY }}-install - name: Restore ninja from cache id: restore_ninja if: ${{ steps.paths.outputs.ninja_SOURCE }} diff --git a/build/fbcode_builder/manifests/glog b/build/fbcode_builder/manifests/glog index 2649eaad1805..b5d5fa814cc2 100644 --- a/build/fbcode_builder/manifests/glog +++ b/build/fbcode_builder/manifests/glog @@ -24,8 +24,7 @@ HAVE_TR1_UNORDERED_SET=OFF [homebrew] glog -# on ubuntu glog brings in liblzma-dev, which in turn breaks watchman tests -[debs.not(distro=ubuntu)] +[debs] libgoogle-glog-dev [rpms.distro=fedora] diff --git a/build/fbcode_builder/manifests/libunwind b/build/fbcode_builder/manifests/libunwind index 560edcd7907d..c73033b798b9 100644 --- a/build/fbcode_builder/manifests/libunwind +++ b/build/fbcode_builder/manifests/libunwind @@ -5,8 +5,7 @@ name = libunwind libunwind-devel libunwind -# on ubuntu this brings in liblzma-dev, which in turn breaks watchman tests -[debs.not(distro=ubuntu)] +[debs] libunwind-dev # The current libunwind v1.8.1 release has compiler issues with aarch64 (https://github.com/libunwind/libunwind/issues/702). diff --git a/build/fbcode_builder/manifests/watchman b/build/fbcode_builder/manifests/watchman index 31596bc938d3..5cdda859f926 100644 --- a/build/fbcode_builder/manifests/watchman +++ b/build/fbcode_builder/manifests/watchman @@ -21,6 +21,9 @@ pcre2 googletest python-setuptools +[dependencies.os=linux] +bz2 + [dependencies.fbsource=on] rust diff --git a/build/fbcode_builder/manifests/xz b/build/fbcode_builder/manifests/xz index 6552f2871a5d..34aeb8493bf5 100644 --- a/build/fbcode_builder/manifests/xz +++ b/build/fbcode_builder/manifests/xz @@ -1,8 +1,7 @@ [manifest] name = xz -# ubuntu's package causes watchman's tests to hang -[debs.not(distro=ubuntu)] +[debs] liblzma-dev [homebrew] diff --git a/watchman/integration/test_age_watch.py b/watchman/integration/test_age_watch.py index 79d6ba43c63d..601ad89c96c4 100644 --- a/watchman/integration/test_age_watch.py +++ b/watchman/integration/test_age_watch.py @@ -35,6 +35,7 @@ def test_watchReap(self) -> None: self.assertWaitFor( lambda: self.rootIsWatched(root), message="%s was not watched by watchman-wait" % root, + timeout=10, ) self.watchmanCommand("trigger-del", root, "t") @@ -44,7 +45,7 @@ def test_watchReap(self) -> None: # subscription won't stick in cli mode if self.transport != "cli": - self.assertWaitFor(lambda: self.rootIsWatched(root)) + self.assertWaitFor(lambda: self.rootIsWatched(root), timeout=10) # let's verify that we can safely reap two roots at once without # causing a deadlock @@ -57,5 +58,6 @@ def test_watchReap(self) -> None: self.assertTrue(unsub["deleted"], "deleted subscription %s" % unsub) # and now we should be ready to reap self.assertWaitFor( - lambda: not self.rootIsWatched(root) and not self.rootIsWatched(second) + lambda: not self.rootIsWatched(root) and not self.rootIsWatched(second), + timeout=10, ) diff --git a/watchman/integration/test_remove.py b/watchman/integration/test_remove.py index 17e5bf7079bf..5516a030c74e 100644 --- a/watchman/integration/test_remove.py +++ b/watchman/integration/test_remove.py @@ -43,4 +43,5 @@ def test_remove(self) -> None: self.assertWaitFor( lambda: not self.rootIsWatched(root), message="%s should be cancelled" % root, + timeout=10, ) diff --git a/watchman/integration/test_request_id.py b/watchman/integration/test_request_id.py index ffa7ee56521b..f947639ff9d2 100644 --- a/watchman/integration/test_request_id.py +++ b/watchman/integration/test_request_id.py @@ -47,10 +47,13 @@ def test_queryRequestId(self) -> None: self.watchmanCommand("query", root, params) pat = re.compile(".* \\[client=.*\\] request_id = %s" % request_id) + print("ntspring waiting 10s for log") self.assertWaitFor( lambda: any(pat.match(l) for l in self.getServerLogContents()), message="request_id logged", + timeout=10, ) + print("ntspring waited for log") def skipIfNoHgRequestIdSupport(self) -> None: root = self.mkdtemp() @@ -131,4 +134,5 @@ def try_read_blackbox(): self.assertWaitFor( lambda: request_id in try_read_blackbox(), message="request_id passed to and logged by hg", + timeout=10, ) diff --git a/watchman/integration/test_sock_perms.py b/watchman/integration/test_sock_perms.py index ab3955555ff9..2df42cfdc2f6 100644 --- a/watchman/integration/test_sock_perms.py +++ b/watchman/integration/test_sock_perms.py @@ -95,6 +95,7 @@ def test_too_open_user_dir(self) -> None: ) self.assertWaitFor( lambda: wanted in instance.getCLILogContents(), + timeout=10, get_debug_output=lambda: instance.getCLILogContents(), ) @@ -123,6 +124,7 @@ def test_invalid_sock_group(self) -> None: self.assertWaitFor( lambda: (wanted in instance.getCLILogContents()) or (we_love_ldap in instance.getCLILogContents()), + timeout=10, get_debug_output=lambda: str(ctx.exception) + "\n" + instance.getCLILogContents(), @@ -137,6 +139,7 @@ def test_user_not_in_sock_group(self) -> None: wanted = "setting up group '%s' failed" % group.gr_name self.assertWaitFor( lambda: wanted in instance.getCLILogContents(), + timeout=10, get_debug_output=lambda: instance.getCLILogContents(), ) @@ -188,7 +191,9 @@ def test_user_previously_in_sock_group(self) -> None: non_member_group.gr_name, ) ) - self.assertWaitFor(lambda: wanted in instance.getServerLogContents()) + self.assertWaitFor( + lambda: wanted in instance.getServerLogContents(), timeout=10 + ) def test_invalid_sock_access(self) -> None: instance = self._new_instance({"sock_access": "bogus"}) @@ -198,6 +203,7 @@ def test_invalid_sock_access(self) -> None: wanted = "Expected config value sock_access to be an object" self.assertWaitFor( lambda: wanted in instance.getCLILogContents(), + timeout=10, get_debug_output=lambda: instance.getCLILogContents(), ) @@ -208,6 +214,7 @@ def test_invalid_sock_access(self) -> None: wanted = "Expected config value sock_access.group to be a boolean" self.assertWaitFor( lambda: wanted in instance.getCLILogContents(), + timeout=10, get_debug_output=lambda: instance.getCLILogContents(), ) diff --git a/watchman/integration/test_trigger.py b/watchman/integration/test_trigger.py index b2eafa7d97f9..efbdb91a169a 100644 --- a/watchman/integration/test_trigger.py +++ b/watchman/integration/test_trigger.py @@ -57,6 +57,7 @@ def test_triggerIssue141(self) -> None: self.assertWaitFor( lambda: os.path.exists(first_log) and os.path.exists(second_log), message="both triggers fire at start", + timeout=10, ) # touch the file, should run both triggers @@ -66,6 +67,7 @@ def test_triggerIssue141(self) -> None: lambda: self.hasTriggerInLogs(root, "first") and self.hasTriggerInLogs(root, "second"), message="both triggers fired on update", + timeout=10, ) def validate_trigger_output(self, root, files, context) -> None: @@ -86,6 +88,7 @@ def files_are_listed(): self.assertWaitFor( lambda: files_are_listed(), message="%s should contain %s" % (trigger_log, json.dumps(files)), + timeout=10, ) def files_are_listed_json(): @@ -106,6 +109,7 @@ def files_are_listed_json(): self.assertWaitFor( lambda: files_are_listed_json(), message="%s should contain %s" % (trigger_json, json.dumps(files)), + timeout=10, ) def test_legacyTrigger(self) -> None: @@ -184,6 +188,7 @@ def test_legacyTrigger(self) -> None: lambda: self.hasTriggerInLogs(root, "test") and self.hasTriggerInLogs(root, "other"), message="both triggers fired on update", + timeout=10, ) self.validate_trigger_output(root, ["foo.c", "b ar.c"], "initial") diff --git a/watchman/integration/test_trigger_chdir.py b/watchman/integration/test_trigger_chdir.py index a624b66f5a3e..a85ba8062777 100644 --- a/watchman/integration/test_trigger_chdir.py +++ b/watchman/integration/test_trigger_chdir.py @@ -67,12 +67,14 @@ def test_triggerChdir(self) -> None: self.assertWaitFor( lambda: self.fileContains( os.path.join(root, "trig.log"), "PWD=" + os.path.join(root, "sub") - ) + ), + timeout=10, ) self.assertWaitFor( lambda: self.fileContains( os.path.join(root, "trig.log"), "WATCHMAN_EMPTY_ENV_VAR=" - ) + ), + timeout=10, ) def test_triggerChdirRelativeRoot(self) -> None: @@ -100,19 +102,22 @@ def test_triggerChdirRelativeRoot(self) -> None: lambda: self.fileContains( os.path.join(root, "trig.log"), "PWD=" + os.path.join(root, "sub1", "sub2"), - ) + ), + timeout=10, ) self.assertWaitFor( lambda: self.fileContains( os.path.join(root, "trig.log"), "WATCHMAN_ROOT=" + root - ) + ), + timeout=10, ) self.assertWaitFor( lambda: self.fileContains( os.path.join(root, "trig.log"), "WATCHMAN_RELATIVE_ROOT=" + os.path.join(root, "sub1"), - ) + ), + timeout=10, ) def test_triggerMaxFiles(self) -> None: @@ -138,7 +143,8 @@ def test_triggerMaxFiles(self) -> None: self.touchRelative(root, "A.txt") self.assertWaitFor( - lambda: self.fileContains(os.path.join(root, "trig.log"), "PWD=" + root) + lambda: self.fileContains(os.path.join(root, "trig.log"), "PWD=" + root), + timeout=10, ) self.assertTrue( @@ -159,7 +165,10 @@ def test_triggerMaxFiles(self) -> None: self.touchRelative(root, "D.txt") self.assertWaitFor( - lambda: self.fileContains(os.path.join(root, "trig.log"), "PWD=" + root) + lambda: self.fileContains( + os.path.join(root, "trig.log"), "PWD=" + root + ), + timeout=10, ) if self.fileContains( @@ -188,13 +197,14 @@ def test_triggerNamePerLine(self) -> None: ) self.touchRelative(root, "A.txt") - self.assertWaitFor(lambda: self.fileContains(log_file, "A.txt")) + self.assertWaitFor(lambda: self.fileContains(log_file, "A.txt"), timeout=10) self.touchRelative(root, "B.txt") self.touchRelative(root, "A.txt") self.assertWaitFor( lambda: self.fileContains(log_file, "A.txt") - and self.fileContains(log_file, "B.txt") + and self.fileContains(log_file, "B.txt"), + timeout=10, ) with open(log_file, "r") as f: self.assertEqual(["A.txt\n", "B.txt\n"], sorted(f.readlines())) @@ -220,7 +230,7 @@ def test_triggerNamePerLineRelativeRoot(self) -> None: self.touchRelative(root, "A.txt") self.touchRelative(root, "subdir", "B.txt") - self.assertWaitFor(lambda: self.fileContains(log_file, "B.txt")) + self.assertWaitFor(lambda: self.fileContains(log_file, "B.txt"), timeout=10) def test_triggerNamePerLineAppend(self) -> None: root = self.mkdtemp() @@ -240,12 +250,13 @@ def test_triggerNamePerLineAppend(self) -> None: ) self.touchRelative(root, "A.txt") - self.assertWaitFor(lambda: self.fileContains(log_file, "A.txt")) + self.assertWaitFor(lambda: self.fileContains(log_file, "A.txt"), timeout=10) self.touchRelative(root, "B.txt") self.assertWaitFor( lambda: self.fileContains(log_file, "A.txt") - and self.fileContains(log_file, "B.txt") + and self.fileContains(log_file, "B.txt"), + timeout=10, ) with open(log_file, "r") as f: self.assertEqual(["A.txt\n", "B.txt\n"], sorted(f.readlines())) @@ -268,7 +279,7 @@ def test_triggerJsonNameOnly(self) -> None: ) self.touchRelative(root, "A.txt") - self.assertWaitFor(lambda: self.fileHasValidJson(log_file)) + self.assertWaitFor(lambda: self.fileHasValidJson(log_file), timeout=10) with open(log_file, "r") as f: data = json.load(f) @@ -292,7 +303,7 @@ def test_triggerJsonNameAndSize(self) -> None: ) self.touchRelative(root, "A.txt") - self.assertWaitFor(lambda: self.fileHasValidJson(log_file)) + self.assertWaitFor(lambda: self.fileHasValidJson(log_file), timeout=10) with open(log_file, "r") as f: data = json.load(f) diff --git a/watchman/integration/test_wm_wait.py b/watchman/integration/test_wm_wait.py index a50edad35a91..026a9cb7ec41 100644 --- a/watchman/integration/test_wm_wait.py +++ b/watchman/integration/test_wm_wait.py @@ -57,6 +57,7 @@ def assertWaitForWmWaitWatch(self, root) -> None: self.assertWaitFor( lambda: self.rootIsWatched(root), message="%s was not watched by watchman-wait" % root, + timeout=10, ) # now wait for it to be ready to query. The easiest way