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

pantsbuild / pants / 24145062409

08 Apr 2026 03:56PM UTC coverage: 52.369% (-40.5%) from 92.91%
24145062409

Pull #23233

github

web-flow
Merge 7a7652ebe into 9036734c9
Pull Request #23233: Introduce a LockfileFormat enum.

7 of 10 new or added lines in 3 files covered. (70.0%)

23048 existing lines in 605 files now uncovered.

31656 of 60448 relevant lines covered (52.37%)

0.52 hits per line

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

92.86
/src/python/pants/backend/terraform/target_types.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
1✔
5

6
from dataclasses import dataclass
1✔
7

8
from pants.engine.internals.native_engine import AddressInput
1✔
9
from pants.engine.rules import collect_rules, rule
1✔
10
from pants.engine.target import (
1✔
11
    COMMON_TARGET_FIELDS,
12
    AllTargets,
13
    AsyncFieldMixin,
14
    Dependencies,
15
    DescriptionField,
16
    FieldSet,
17
    MultipleSourcesField,
18
    SingleSourceField,
19
    StringField,
20
    Target,
21
    Targets,
22
    generate_multiple_sources_field_help_message,
23
)
24
from pants.util.strutil import help_text, softwrap
1✔
25

26

27
class TerraformDependenciesField(Dependencies):
1✔
28
    pass
1✔
29

30

31
class TerraformModuleSourcesField(MultipleSourcesField):
1✔
32
    default = ("*.tf",)
1✔
33
    expected_file_extensions = (".tf",)
1✔
34
    ban_subdirectories = True
1✔
35
    help = generate_multiple_sources_field_help_message(
1✔
36
        "Example: `sources=['example.tf', 'new_*.tf', '!old_ignore.tf']`"
37
    )
38

39

40
@dataclass(frozen=True)
1✔
41
class TerraformFieldSet(FieldSet):
1✔
42
    required_fields = (TerraformModuleSourcesField,)
1✔
43

44
    sources: TerraformModuleSourcesField
1✔
45
    dependencies: TerraformDependenciesField
1✔
46

47

48
class TerraformModuleTarget(Target):
1✔
49
    alias = "terraform_module"
1✔
50
    core_fields = (*COMMON_TARGET_FIELDS, TerraformDependenciesField, TerraformModuleSourcesField)
1✔
51
    help = help_text(
1✔
52
        """
53
        A single Terraform module corresponding to a directory.
54

55
        There must only be one `terraform_module` in a directory.
56

57
        Use `terraform_modules` to generate `terraform_module` targets for less boilerplate.
58
        """
59
    )
60

61

62
class TerraformRootModuleField(StringField, AsyncFieldMixin):
1✔
63
    """The module to use as the root module for a Terraform deployment."""
64

65
    required = True
1✔
66
    alias = "root_module"
1✔
67
    help = help_text(
1✔
68
        """
69
        The Terraform module to use as the root module.
70

71
        Example: `root_module=":my_module"`
72
        """
73
    )
74

75
    def to_address_input(self) -> AddressInput:
1✔
UNCOV
76
        if not self.value:
×
77
            raise ValueError(
×
78
                softwrap(
79
                    f"""
80
            A Terraform deployment must have a nonempty {self.alias} field,
81
             but {self.address} was empty"""
82
                )
83
            )
UNCOV
84
        return AddressInput.parse(
×
85
            self.value,
86
            relative_to=self.address.spec_path,
87
            description_of_origin=f"the `{self.alias} field in the `{TerraformDeploymentTarget.alias}` target {self.address}",
88
        )
89

90

91
class TerraformBackendConfigField(SingleSourceField):
1✔
92
    default = ".tfbackend"
1✔
93
    help = "Configuration to be merged with what is in the root module's 'backend' block"
1✔
94

95

96
class TerraformBackendTarget(Target):
1✔
97
    alias = "terraform_backend"
1✔
98
    core_fields = (*COMMON_TARGET_FIELDS, TerraformBackendConfigField)
1✔
99
    help = "Configuration to be merged with what is in the root module's 'backend' block"
1✔
100

101

102
class TerraformVarFileSourceField(MultipleSourcesField):
1✔
103
    default = ("*.tfvars",)
1✔
104
    expected_file_extensions = (".tfvars",)
1✔
105
    help = generate_multiple_sources_field_help_message(
1✔
106
        "Example: `sources=['common.tfvars', 'prod.tfvars']`"
107
    )
108

109

110
class TerraformVarFileTarget(Target):
1✔
111
    alias = "terraform_var_files"
1✔
112
    core_fields = (*COMMON_TARGET_FIELDS, TerraformVarFileSourceField)
1✔
113
    help = "Terraform vars files"
1✔
114

115

116
class TerraformDeploymentTarget(Target):
1✔
117
    alias = "terraform_deployment"
1✔
118
    core_fields = (
1✔
119
        *COMMON_TARGET_FIELDS,
120
        TerraformDependenciesField,
121
        TerraformRootModuleField,
122
    )
123
    help = "A deployment of Terraform"
1✔
124

125

126
@dataclass(frozen=True)
1✔
127
class TerraformDeploymentFieldSet(FieldSet):
1✔
128
    required_fields = (
1✔
129
        TerraformDependenciesField,
130
        TerraformRootModuleField,
131
    )
132
    description: DescriptionField
1✔
133
    root_module: TerraformRootModuleField
1✔
134
    dependencies: TerraformDependenciesField
1✔
135

136

137
class AllTerraformDeploymentTargets(Targets):
1✔
138
    pass
1✔
139

140

141
@rule
1✔
142
async def all_terraform_deployment_targets(targets: AllTargets) -> AllTerraformDeploymentTargets:
1✔
143
    return AllTerraformDeploymentTargets(
×
144
        tgt for tgt in targets if TerraformDeploymentFieldSet.is_applicable(tgt)
145
    )
146

147

148
class LockfileSourceField(SingleSourceField):
1✔
149
    """Source field for synthesized `_lockfile` targets."""
150

151
    default = ".terraform.lock.hcl"
1✔
152

153

154
class LockfileDependenciesField(Dependencies):
1✔
155
    pass
1✔
156

157

158
class TerraformLockfileTarget(Target):
1✔
159
    alias = "_terraform_lockfile"
1✔
160
    core_fields = (*COMMON_TARGET_FIELDS, LockfileSourceField, LockfileDependenciesField)
1✔
161
    help = help_text(
1✔
162
        """
163
        A target for lockfiles in order to include them in the dependency graph of other targets.
164

165
        This tracks them so that `--changed-since --changed-dependents` works properly for targets
166
        relying on a particular lockfile.
167
        """
168
    )
169

170

171
def rules():
1✔
172
    return collect_rules()
×
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