mirror of
https://github.com/hashicorp/terraform.git
synced 2026-03-21 10:00:09 -04:00
153 lines
7.4 KiB
Markdown
153 lines
7.4 KiB
Markdown
# Upgrading Terraform's Library Dependencies
|
|
|
|
This codebase depends on a variety of external Go modules. At the time of
|
|
writing, a Terraform CLI build includes the union of all dependencies required
|
|
by Terraform CLI and Core itself and each of the remote state backends.
|
|
|
|
Because the remote state backends have quite a different set of needs than
|
|
Terraform itself -- special client libraries, in particular -- we've declared
|
|
them as being separate Go Modules with their own `go.mod` and `go.sum` files,
|
|
even though we don't intend to ever publish them separately. The goal is just
|
|
to help track which dependencies are used by each of these components, and to
|
|
more easily determine which of the components are affected by a particular
|
|
dependency upgrade so that we can make sure to do the appropriate testing.
|
|
|
|
## Dependency Synchronization
|
|
|
|
Because all of these components ultimately link into the same executable, there
|
|
can be only one version of each distinct module and thus all of the modules
|
|
must agree on which version to use.
|
|
|
|
The makefile target `syncdeps` runs a script which synchronizes all of the
|
|
modules to declare compatible dependencies, selecting the newest version of
|
|
each external module selected across all of the internal modules:
|
|
|
|
```shell
|
|
make syncdeps
|
|
```
|
|
|
|
After running this, use `git status` to see what's been changed. If you've
|
|
changed the dependencies of any of the modules then that should typically
|
|
cause an update to the root module, because that one imports all of the others.
|
|
|
|
## Upgrading a Dependency
|
|
|
|
To select a newer version of one of the dependencies, use `go get` in the
|
|
root to specify which version to use:
|
|
|
|
```shell
|
|
go get example.com/foo/bar@v1.0.0
|
|
```
|
|
|
|
Or, if you just want to move to the latest stable release, you can use the
|
|
`latest` pseudo-version:
|
|
|
|
```shell
|
|
go get example.com/foo/bar@latest
|
|
```
|
|
|
|
Then run `make syncdeps` to update any of the child modules that also use
|
|
this dependency. The remote state backends use only a subset of the packages
|
|
in Terraform CLI/Core, so not all dependency updates will affect the remote
|
|
state backends, and an update might affect only a subset of the backends.
|
|
|
|
When you open the pull request for your change, our code owners rules will
|
|
automatically request review from the team that maintains any affected remote
|
|
state backend. The affected teams can judge whether the update seems likely
|
|
to affect their backend and run their acceptance tests if so, before approving
|
|
the pull request. As usual, these PRs should also be reviewed by at least
|
|
one member of the Terraform Core team since they are ultimately responsible
|
|
for the complete set of dependencies used in Terraform CLI releases.
|
|
|
|
**Note:** Currently our code owners rules are simplistic and will request
|
|
review for _any_ change under a remote state backend module directory, but
|
|
in practice an update that only changes a backend's `go.sum` cannot affect
|
|
the runtime behavior of the backend, and so those review requests are not
|
|
strictly required. You should therefore remove the review requests for
|
|
any backend whose only diff is the `go.sum` file once you've opened the
|
|
pull request.
|
|
|
|
## Dependabot Updates
|
|
|
|
When Dependabot automatically opens a pull request to upgrade a dependency,
|
|
unfortunately it isn't smart enough to automatically synchronize the change
|
|
across the modules and so the code consistency checks for the change will
|
|
typically fail.
|
|
|
|
To apply the proposed change, you'll need to check out the branch that
|
|
Dependabot created on your development system, run `make syncdeps`, add
|
|
all of the files that get modified, and then amend Dependabot's commit using
|
|
`git commit --amend`.
|
|
|
|
After you've done this, use `git push --force` to replace Dependabot's original
|
|
commit with your new commit, and then wait for GitHub to re-run the PR
|
|
checks. The code consistency checks should now pass.
|
|
|
|
We've configured Dependabot to monitor only the root `go.mod` file for potential
|
|
upgrades, because that one aggregates the dependencies for all other child
|
|
modules. Therefore there should never be a Dependabot upgrade targeting a
|
|
module in a subdirectory. If one _does_ get created somehow, you should close
|
|
it and perform the same upgrade at the root of the repository instead, using
|
|
the instructions in [Upgrading a Dependency](#upgrading-a-dependency) above.
|
|
|
|
## Dependencies with Special Requirements
|
|
|
|
Most of our dependencies can be treated generically, but a few have some
|
|
special constraints due to how Terraform uses them:
|
|
|
|
* HCL, cty, and their indirect dependencies `golang.org/x/text` and
|
|
`github.com/apparentlymart/go-textseg` all include logic based on Unicode
|
|
specifications, and so should be updated with care to make sure that
|
|
Terraform's support for Unicode follows a consistent Unicode version
|
|
throughout.
|
|
|
|
Additionally, each time we adopt a new minor release of Go, we may need to
|
|
upgrade some or all of these dependencies to match the Unicode version used
|
|
by the Go standard library.
|
|
|
|
For more information, refer to [How Terraform Uses Unicode](unicode.md).
|
|
|
|
(This concern does not apply if the new version we're upgrading to is built
|
|
for the same version of Unicode that Terraform was already using.)
|
|
|
|
* `github.com/hashicorp/go-getter` represents a significant part of Terraform
|
|
CLI's remote module installer, and is the final interpreter of Terraform's
|
|
module source address syntax. Because the module source address syntax is
|
|
protected by the Terraform v1.x Compatibility Promises, for each upgrade
|
|
we must make sure that:
|
|
|
|
- The upgrade doesn't expand the source address syntax in a way that is
|
|
undesirable from a Terraform product standpoint or in a way that we would
|
|
not feel comfortable supporting indefinitely under the compatibility
|
|
promises.
|
|
- The upgrade doesn't break any already-supported source address forms
|
|
that would therefore cause the next Terraform version to break the
|
|
v1.x compatibility promises.
|
|
|
|
Terraform's use of `go-getter` is all encapsulated in `internal/getmodules`
|
|
and is set up to try to minimize the possibility that a go-getter upgrade
|
|
would immediately introduce new functionality, but that encapsulation cannot
|
|
prevent adoption of changes made to pre-existing functionality that
|
|
Terraform already exposes.
|
|
|
|
* `github.com/hashicorp/go-tfe` -- the client library for the HCP Terraform
|
|
API -- includes various types corresponding to HCP Terraform API
|
|
requests and responses. The internal package `internal/cloud` contains mock
|
|
implementations of some of those types, which may need to be updated when
|
|
the client library is upgraded.
|
|
|
|
These upgrades should typically be done only in conjunction with a project
|
|
that will somehow use the new features through the Cloud integration, so
|
|
that the team working on that project can perform any needed updates to
|
|
the mocks as part of their work.
|
|
|
|
* `go.opentelemetry.io/otel` and the other supporting OpenTelemetry modules
|
|
should typically be upgraded together in lockstep, because some of the
|
|
modules define interfaces that other modules implement, and strange behavior
|
|
can emerge if one is upgraded without the other.
|
|
|
|
The main modules affected by this rule are the ones under the
|
|
`go.opentelemetry.io/otel` prefix. The "contrib" packages can be trickier
|
|
to upgrade because they tend to have dependencies that overlap with ours
|
|
and so might affect non-telemetry-related behavior, and so it's acceptable
|
|
for those to lag slightly behind to reduce risk in routine upgrades.
|