forked from pantsbuild/pants
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[internal] Hook up
check
to Go (pantsbuild#13322)
This lets you compile a package without needing to run tests or package a binary. Note that you can only directly compile a first-party package - to check if a third-party package is buildable, it must be a dependency of a first-party package. Works around pantsbuild#13175. This does not yet have an optimal UX. It's overly chatty: ``` ❯ ./pants check testprojects/src/go:: 13:36:38.57 [INFO] Initializing scheduler... 13:36:39.20 [INFO] Scheduler initialized. 13:36:39.71 [ERROR] Completed: pants.backend.go.goals.check.check_go - go failed (exit code 1). Partition #1 - github.com/pantsbuild/pants/testprojects/src/go/pants_test: ./testprojects/src/go/pants_test/foo.go:3:1: syntax error: non-declaration statement outside function body Partition #2 - github.com/pantsbuild/pants/testprojects/src/go/pants_test/bar: 𐄂 go failed. ``` We also should be streaming the result of each compilation as it happens, which has an added benefit of that output happening when compilation happens as a side effect of `run`, `package`, and `test`. Those fixes will be in a followup. [ci skip-rust] [ci skip-build-wheels]
- Loading branch information
1 parent
5a2207a
commit 16dd4e0
Showing
3 changed files
with
163 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from dataclasses import dataclass | ||
from typing import cast | ||
|
||
from pants.backend.go.target_types import GoFirstPartyPackageSourcesField | ||
from pants.backend.go.util_rules.build_pkg import ( | ||
BuildGoPackageRequest, | ||
BuildGoPackageTargetRequest, | ||
FallibleBuildGoPackageRequest, | ||
FallibleBuiltGoPackage, | ||
) | ||
from pants.core.goals.check import CheckRequest, CheckResult, CheckResults | ||
from pants.engine.rules import Get, MultiGet, collect_rules, rule | ||
from pants.engine.target import FieldSet | ||
from pants.engine.unions import UnionRule | ||
|
||
|
||
@dataclass(frozen=True) | ||
class GoCheckFieldSet(FieldSet): | ||
required_fields = (GoFirstPartyPackageSourcesField,) | ||
|
||
sources: GoFirstPartyPackageSourcesField | ||
|
||
|
||
class GoCheckRequest(CheckRequest): | ||
field_set_type = GoCheckFieldSet | ||
|
||
|
||
@rule | ||
async def check_go(request: GoCheckRequest) -> CheckResults: | ||
build_requests = await MultiGet( | ||
Get(FallibleBuildGoPackageRequest, BuildGoPackageTargetRequest(field_set.address)) | ||
for field_set in request.field_sets | ||
) | ||
invalid_requests = [] | ||
valid_requests = [] | ||
for fallible_request in build_requests: | ||
if fallible_request.request is None: | ||
invalid_requests.append(fallible_request) | ||
else: | ||
valid_requests.append(fallible_request.request) | ||
|
||
build_results = await MultiGet( | ||
Get(FallibleBuiltGoPackage, BuildGoPackageRequest, request) for request in valid_requests | ||
) | ||
|
||
# TODO: Update `build_pkg.py` to use streaming workunits to log compilation results, which has | ||
# the benefit of other contexts like `test.py` using it. Switch this to only preserve the | ||
# exit code. | ||
check_results = [ | ||
*( | ||
CheckResult( | ||
result.exit_code, | ||
"", | ||
cast(str, result.stderr), | ||
partition_description=result.import_path, | ||
) | ||
for result in invalid_requests | ||
), | ||
*( | ||
CheckResult( | ||
result.exit_code, | ||
result.stdout or "", | ||
result.stderr or "", | ||
partition_description=result.import_path, | ||
) | ||
for result in build_results | ||
), | ||
] | ||
return CheckResults(check_results, checker_name="go") | ||
|
||
|
||
def rules(): | ||
return [*collect_rules(), UnionRule(CheckRequest, GoCheckRequest)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from __future__ import annotations | ||
|
||
from textwrap import dedent | ||
|
||
import pytest | ||
|
||
from pants.backend.go import target_type_rules | ||
from pants.backend.go.goals import check | ||
from pants.backend.go.goals.check import GoCheckFieldSet, GoCheckRequest | ||
from pants.backend.go.target_types import GoModTarget | ||
from pants.backend.go.util_rules import ( | ||
assembly, | ||
build_pkg, | ||
first_party_pkg, | ||
go_mod, | ||
import_analysis, | ||
sdk, | ||
third_party_pkg, | ||
) | ||
from pants.core.goals.check import CheckResult, CheckResults | ||
from pants.engine.addresses import Address | ||
from pants.testutil.rule_runner import QueryRule, RuleRunner | ||
|
||
|
||
@pytest.fixture | ||
def rule_runner() -> RuleRunner: | ||
rule_runner = RuleRunner( | ||
rules=[ | ||
*check.rules(), | ||
*sdk.rules(), | ||
*assembly.rules(), | ||
*build_pkg.rules(), | ||
*import_analysis.rules(), | ||
*go_mod.rules(), | ||
*first_party_pkg.rules(), | ||
*third_party_pkg.rules(), | ||
*target_type_rules.rules(), | ||
QueryRule(CheckResults, [GoCheckRequest]), | ||
], | ||
target_types=[GoModTarget], | ||
) | ||
rule_runner.set_options([], env_inherit={"PATH"}) | ||
return rule_runner | ||
|
||
|
||
def test_check(rule_runner: RuleRunner) -> None: | ||
rule_runner.write_files( | ||
{ | ||
"go.mod": dedent( | ||
"""\ | ||
module example.com/greeter | ||
go 1.17 | ||
""" | ||
), | ||
"bad/f.go": "invalid!!!", | ||
"good/f.go": dedent( | ||
"""\ | ||
package greeter | ||
import "fmt" | ||
func Hello() { | ||
fmt.Println("Hello world!") | ||
} | ||
""" | ||
), | ||
"BUILD": "go_mod(name='mod')", | ||
} | ||
) | ||
targets = [ | ||
rule_runner.get_target(Address("", target_name="mod", generated_name="./bad")), | ||
rule_runner.get_target(Address("", target_name="mod", generated_name="./good")), | ||
] | ||
results = rule_runner.request( | ||
CheckResults, [GoCheckRequest(GoCheckFieldSet.create(tgt) for tgt in targets)] | ||
).results | ||
assert set(results) == { | ||
CheckResult(0, "", "", "example.com/greeter/good"), | ||
CheckResult( | ||
1, "", "bad/f.go:1:1: expected 'package', found invalid\n", "example.com/greeter/bad" | ||
), | ||
} |