• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 26342152999

23 May 2026 07:59PM UTC coverage: 91.165% (-1.6%) from 92.792%
26342152999

push

github

web-flow
Run Linux ARM CI on Depot runners (#23363)

RunsOn is deprecating their v2 stack, and rather than migrate
to v3 we should use the resources kindly donated by Depot.

GitHub also now has Linux ARM runners, should we need them.

87305 of 95766 relevant lines covered (91.16%)

3.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.52
/src/python/pants/backend/go/util_rules/goroot.py
1
# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3
from __future__ import annotations
11✔
4

5
import json
11✔
6
import logging
11✔
7
from dataclasses import dataclass
11✔
8

9
from pants.backend.go.subsystems.golang import GolangSubsystem
11✔
10
from pants.backend.go.util_rules import go_bootstrap
11✔
11
from pants.backend.go.util_rules.go_bootstrap import GoBootstrap, compatible_go_version
11✔
12
from pants.core.environments.target_types import EnvironmentTarget
11✔
13
from pants.core.util_rules.system_binaries import (
11✔
14
    BinaryNotFoundError,
15
    BinaryPathRequest,
16
    BinaryPathTest,
17
    find_binary,
18
)
19
from pants.engine.internals.selectors import concurrently
11✔
20
from pants.engine.process import Process, fallible_to_exec_result_or_raise
11✔
21
from pants.engine.rules import collect_rules, implicitly, rule
11✔
22
from pants.util.frozendict import FrozenDict
11✔
23
from pants.util.logging import LogLevel
11✔
24
from pants.util.strutil import bullet_list, softwrap
11✔
25

26
logger = logging.getLogger(__name__)
11✔
27

28

29
@dataclass(frozen=True)
11✔
30
class GoRoot:
11✔
31
    """Path to the Go installation (the `GOROOT`)."""
32

33
    path: str
11✔
34
    version: str
11✔
35

36
    _raw_metadata: FrozenDict[str, str]
11✔
37

38
    def is_compatible_version(self, version: str) -> bool:
11✔
39
        """Can this Go compiler handle the target version?"""
40
        return compatible_go_version(compiler_version=self.version, target_version=version)
11✔
41

42
    def major_version(self, version: str) -> str:
11✔
43
        _version_components = version.split(".")  # e.g. [1, 17] or [1, 17, 1]
10✔
44
        major_version = ".".join(_version_components[:2])
10✔
45
        return major_version
10✔
46

47
    @property
11✔
48
    def full_version(self) -> str:
11✔
49
        return self._raw_metadata["GOVERSION"]
11✔
50

51
    @property
11✔
52
    def goos(self) -> str:
11✔
53
        return self._raw_metadata["GOOS"]
11✔
54

55
    @property
11✔
56
    def goarch(self) -> str:
11✔
57
        return self._raw_metadata["GOARCH"]
11✔
58

59

60
@rule(desc="Find Go binary", level=LogLevel.DEBUG)
11✔
61
async def setup_goroot(
11✔
62
    golang_subsystem: GolangSubsystem, go_bootstrap: GoBootstrap, env_target: EnvironmentTarget
63
) -> GoRoot:
64
    search_paths = go_bootstrap.go_search_paths
11✔
65
    all_go_binary_paths = await find_binary(
11✔
66
        BinaryPathRequest(
67
            search_path=search_paths,
68
            binary_name="go",
69
            test=BinaryPathTest(["version"]),
70
        ),
71
        **implicitly(),
72
    )
73
    if not all_go_binary_paths.paths:
11✔
74
        raise BinaryNotFoundError(
×
75
            softwrap(
76
                f"""
77
                Cannot find any `go` binaries using the option `[golang].go_search_paths`:
78
                {list(search_paths)}
79

80
                To fix, please install Go (https://golang.org/doc/install) with the version
81
                {golang_subsystem.minimum_expected_version} or newer (set by
82
                `[golang].minimum_expected_version`). Then ensure that it is discoverable via
83
                `[golang].go_search_paths`.
84
                """
85
            )
86
        )
87

88
    # `go env GOVERSION` does not work in earlier Go versions (like 1.15), so we must run
89
    # `go version` and `go env GOROOT` to calculate both the version and GOROOT.
90
    version_results = await concurrently(
11✔
91
        fallible_to_exec_result_or_raise(
92
            **implicitly(
93
                Process(
94
                    (binary_path.path, "version"),
95
                    description=f"Determine Go version for {binary_path.path}",
96
                    level=LogLevel.DEBUG,
97
                    cache_scope=env_target.executable_search_path_cache_scope(),
98
                )
99
            )
100
        )
101
        for binary_path in all_go_binary_paths.paths
102
    )
103

104
    invalid_versions = []
11✔
105
    for binary_path, version_result in zip(all_go_binary_paths.paths, version_results):
11✔
106
        try:
11✔
107
            _raw_version = version_result.stdout.decode("utf-8").split()[
11✔
108
                2
109
            ]  # e.g. go1.17 or go1.17.1
110
            _version_components = _raw_version[2:].split(".")  # e.g. [1, 17] or [1, 17, 1]
11✔
111
            version = f"{_version_components[0]}.{_version_components[1]}"
11✔
112
        except IndexError:
×
113
            raise AssertionError(
×
114
                f"Failed to parse `go version` output for {binary_path}. Please open a bug at "
115
                f"https://github.com/pantsbuild/pants/issues/new/choose with the below data."
116
                f"\n\n"
117
                f"{version_result}"
118
            )
119

120
        if compatible_go_version(
11✔
121
            compiler_version=version, target_version=golang_subsystem.minimum_expected_version
122
        ):
123
            env_result = await fallible_to_exec_result_or_raise(
11✔
124
                **implicitly(
125
                    Process(
126
                        (binary_path.path, "env", "-json"),
127
                        description=f"Determine Go SDK metadata for {binary_path.path}",
128
                        level=LogLevel.DEBUG,
129
                        cache_scope=env_target.executable_search_path_cache_scope(),
130
                        env={"GOPATH": "/does/not/matter"},
131
                    )
132
                )
133
            )
134
            sdk_metadata = json.loads(env_result.stdout.decode())
11✔
135
            return GoRoot(
11✔
136
                path=sdk_metadata["GOROOT"], version=version, _raw_metadata=FrozenDict(sdk_metadata)
137
            )
138

139
        logger.debug(
×
140
            f"Go binary at {binary_path.path} has version {version}, but this "
141
            f"repository expects at least {golang_subsystem.minimum_expected_version} "
142
            "(set by `[golang].expected_minimum_version`). Ignoring."
143
        )
144

145
        invalid_versions.append((binary_path.path, version))
×
146

147
    invalid_versions_str = bullet_list(
×
148
        f"{path}: {version}" for path, version in sorted(invalid_versions)
149
    )
150
    raise BinaryNotFoundError(
×
151
        softwrap(
152
            f"""
153
            Cannot find a `go` binary compatible with the minimum version of
154
            {golang_subsystem.minimum_expected_version} (set by `[golang].minimum_expected_version`).
155

156
            Found these `go` binaries, but they had incompatible versions:
157

158
            {invalid_versions_str}
159

160
            To fix, please install the expected version or newer (https://golang.org/doc/install)
161
            and ensure that it is discoverable via the option `[golang].go_search_paths`, or change
162
            `[golang].expected_minimum_version`.
163
            """
164
        )
165
    )
166

167

168
def rules():
11✔
169
    return (
11✔
170
        *collect_rules(),
171
        *go_bootstrap.rules(),
172
    )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc