Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Pants hosted Go toolchain #20485

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open

Conversation

tgolsson
Copy link
Contributor

@tgolsson tgolsson commented Feb 2, 2024

This adds a new feature where Pants provides a Go toolchain for commands, removing the need for the host system to have one. I've been on the fence about supporting the old method, but opted to keep it for now with a deprecation warning. This will let us iron out any issues that might arise from this without too much risk.

I've been trying to find any significant performance regressions, but there's so much noise in tests that it's hard to tell.

Test Main Symlinked toolchain Bundled toolchain
dependency_inference_test.py 38.82s 31.06s 27.96s
goals/check_test.py 26.94s 22.86s 27.59s
goals/generate_test.py 36.58s 29.75s 26.51s
goals/package_binary_integration_test.py 55.83s 51.95s 74.23s
goals/run_binary_integration_test.py 86.53s 53.33s 80.78s
goals/tailor_test.py 5.96s 7.25s 15.71s
goals/test_test.py 177.80s 165.98s 100.19s
lint/gofmt/rules_integration_test.py 5.59s 7.01s 9.26s
lint/golangci_lint/rules_integration_test.py 79.10s 72.61s 70.78s
lint/vet/rules_integration_test.py 40.21s 33.94s 37.88s
target_type_rules_test.py 70.16s 56.75s 60.15s
util_rules/assembly_integration_test.py 72.63s 71.66s 67.82s
util_rules/build_opts_test.py 81.04s 79.68s 79.78s
util_rules/build_pkg_target_test.py 55.75s 83.16s 85.19s
util_rules/build_pkg_test.py 6.11s 5.41s 9.88s
util_rules/cgo_pkgconfig_test.py 1.57s 1.72s 2.98s
util_rules/cgo_security_test.py 1.08s 1.30s 1.91s
util_rules/cgo_test.py 77.65s 95.11s 135.30s
util_rules/coverage_profile_test.py 1.85s 2.26s 2.83s
util_rules/coverage_test.py 60.55s 47.11s 52.19s
util_rules/embed_integration_test.py 101.48s 105.35s 49.19s
util_rules/first_party_pkg_test.py 59.11s 48.26s 59.11s
util_rules/go_bootstrap_test.py 2.09s 1.62s 1.15s
util_rules/go_mod_test.py 4.28s 4.04s 2.85s
util_rules/goroot_test.py 3.32s 2.58s 4.65s
util_rules/import_analysis_test.py 9.88s 12.54s 10.55s
util_rules/import_config_test.py 3.02s 2.98s 3.25s
util_rules/pkg_pattern_test.py 1.13s 1.50s 1.54s
util_rules/tests_analysis_test.py 51.67s 53.30s 48.38s
util_rules/third_party_pkg_test.py 78.83s 68.79s 61.92s
util_rules/vendor_test.py 23.11s 17.71s 23.46s

All tests ran on same machine, same command, etc. If anyone wants to do similar tests the command is pants --process-execution-local-parallelism=8 test --force src/python/pants/backend/go/::

I'd ignore most test files during review, then start with goroot.py and take rules after. Most of the changes are the same to include the new goroot input cache. I've not written any new tests -- the new codepath is exercised in every test since I've enabled this by default.

Opinions on default Go version are welcome.

@tgolsson tgolsson added backend: Go Go backend-related issues category:new feature labels Feb 2, 2024
@tgolsson tgolsson force-pushed the ts/go-toolchain branch 2 times, most recently from eaf3355 to 7754a60 Compare March 19, 2024 20:44
@tgolsson tgolsson marked this pull request as ready for review March 21, 2024 12:06
@tgolsson tgolsson requested a review from tdyas March 21, 2024 12:08
@@ -819,7 +826,7 @@ async def cgo_compile_request(
env=cgo_env,
description=f"Generate Go and C files from CGo files ({request.import_path})",
input_digest=cgo_input_digest,
output_directories=(obj_dir_path,),
output_directories=(obj_dir_path, "!.goroot"),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugly but needed since we capture '.'

export GOPATH="${{sandbox_root}}/gopath"
export GOCACHE="${{sandbox_root}}/cache"
export GOROOT="${{sandbox_root}}/{goroot.path}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has to be absolute here, hence restructure. Could maybe do realpath...

@@ -141,6 +141,13 @@ def strip_v2_chroot_path(v: bytes | str) -> str:
return re.sub(r"/.*/pants-sandbox-[a-zA-Z0-9]+/", "", v)


# NB: As above but doesn't convert to str.
def strip_v2_chroot_path_bytes(v: bytes) -> bytes:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ijson wants bytes, this satisfies that to avoid keeping sandbox-paths around in the outputs as that breaks later

@tgolsson tgolsson mentioned this pull request Mar 28, 2024
4 tasks
Copy link
Member

@cognifloyd cognifloyd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hesitant about pants providing the go toolchain, but I'm more ok with that now. I'm especially OK with that if we make the go toolchain an ExportableTool (possibly as a symlinked_immutable export?).

I noticed one (inconsequential) inconsistency. Even with that, this looks good to me.

@huonw
Copy link
Contributor

huonw commented May 10, 2024

When you have a chance, please merge main (or rebase onto it) and add some release notes to docs/notes/2.22.x.md. See #20888 for more info.

@tgolsson
Copy link
Contributor Author

@huonw Added notes

@@ -66,6 +66,12 @@ The deprecation for the `platforms` field for the `pex_binary` and `pex_binaries

Setting [the `orphan_files_behaviour = "ignore"` option](https://www.pantsbuild.org/2.22/reference/subsystems/yamllint#orphan_files_behavior) the `pants.backend.experimental.tools.yamllint` backend is now properly silent. It previously showed spurious warnings.

#### Golang

Pants will now automatically install a Golang toolchain when needed, removing the need for installing it externally. This can be configured by `[go-toolchain].known_versions`, `[go-toolchain].enabled`, and `[go-toolchain].version`. As of shipping, you can select a version from *1.18.10*, *1.19.13*, *1.20.13*, and *1.21.6*. Other versions can be configured by adding to the known versions. Note that versions after Go 1.21 are currently not official supported due to the coverage system redesign. PRs are welcome here.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that versions after Go 1.21 are currently not official supported due to the coverage system redesign.

I assume the prior coverage system went away in more recent Go versions?


Pants will now automatically install a Golang toolchain when needed, removing the need for installing it externally. This can be configured by `[go-toolchain].known_versions`, `[go-toolchain].enabled`, and `[go-toolchain].version`. As of shipping, you can select a version from *1.18.10*, *1.19.13*, *1.20.13*, and *1.21.6*. Other versions can be configured by adding to the known versions. Note that versions after Go 1.21 are currently not official supported due to the coverage system redesign. PRs are welcome here.

The `[go-toolchain].enabled` flag is shipped and immediately deprecated, with the goal of only supporting a Pants-provided Go toolchain in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this in fact what users want? What if a user still wants to provide their own Go toolchain? Maybe we should not deprecate until we actually decide and intend to remove support for user-provided Go toolchains?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a "upgrade/process/release manager" perspective (I know nothing about Go), just reiterating that it might be good to at least have a release or two for it to bake and generally try to make upgrades easier. If we deprecate immediately and there's some bugs:

  • it'll be annoying for users to stick with the old version (they'll get warnings they can't action, constantly)
  • those bugs may need to be treated as higher severity by us (Pants maintainers) and need "immediate" attention, because they'll potentially be breaking existing code or making it hard for new users to onboard. This might then mean we have to delay releases to wait for fixes... and it's nicer for everyone to not have any of that panic.

One approach might be to: add the option without an explicit default. If it's not set:

  • emit a deprecation warning (i.e. tell people that it must be set and that the default will change), and
  • fall back to whichever values matches the current behaviour (to ease the upgrade path by not changing behaviour immediately).

Future releases can then continue the phasing out, e.g. a fairly conservative potential path might be:

release option default old behaviour new behaviour
2.22 (this PR) added, deprecation when not set old not deprecated, unchanged added
2.23 default changed new unchanged unchanged, default
2.24 no deprecation when not set (just get new behaviour silently) new unchanged unchanged
2.25 deprecated when set at all new deprecated unchanged
2.26 waiting... new waiting... unchanged
2.27 removed new removed unchanged

It looks like Go backend is experimental, so we can almost certainly do a more aggressive timeline than that... but I think we at least want to have:

  • one release where users can opt-in to either the old behaviour or the new behaviour, and doesn't get warnings once they do the opt-in
  • one release where the old behaviour exists but has deprecation warnings

What do you think?

@@ -74,6 +75,7 @@ async def gofmt_fmt(
output_files=request.files,
description=f"Run gofmt on {pluralize(len(request.files), 'file')}.",
level=LogLevel.DEBUG,
immutable_input_digests={".goroot": goroot.digest},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see .goroot in several places. Maybe it should be a constant?

If true, Pants will provide a Go distribution instead of requiring one to be installed on the host system.
"""
),
deprecation_start_version="2.22.0.dev2",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See other comment about when to start deprecating.

@@ -579,6 +580,7 @@ async def resolve_go_stdlib_embed_config(
input_digest=input_digest,
description=f"Create embed mapping for {request.package.import_path}",
level=LogLevel.DEBUG,
immutable_input_digests={".goroot": goroot.digest},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe have a goroot.immutable_input_digests function which returns this dictionary?

env_result = await Get( # noqa: PNT30: requires triage
ProcessResult,
Process(
(".goroot/go/bin/go", "env", "-json"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use binary_path here?

) -> GoRoot:
if toolchain_subsystem.enabled:
go_sdk = await Get(GoRoot, InstallGoToolchainRequest())

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra newline

Copy link
Contributor

@huonw huonw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've just branched for 2.22, so merging this pull request now will come out in 2.23, please move the release notes updates to docs/notes/2.23.x.md.

@huonw
Copy link
Contributor

huonw commented Sep 11, 2024

We've just branched for 2.23 2.25, so merging this pull request now will come out in 2.24 2.26, please move the release notes updates to docs/notes/2.26.x.md.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend: Go Go backend-related issues category:new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants