Two upstream repositories
=========================

As of this upload this source pkg is built from _two_ upstream git repos which
Google tag independently of one another:

  1. guest-agent @ https://github.com/GoogleCloudPlatform/guest-agent
     The old, "classic" agent. Unpacks to the top level of the source tree and
     is built by `dh-golang`. Provides the following binaries:
       * google_guest_agent
       * google_metadata_script_runner
       * gce_workload_cert_refresh

  2. google-guest-agent @ https://github.com/GoogleCloudPlatform/google-guest-agent
     The new plugin manager (confusingly named the same as this source pkg)
     Shipped as a component orig tarball that `dpkg-source` unpacks into
     `./google-guest-agent/`. Provides the following binaries:
       * google_guest_agent_manager (from `cmd/google_guest_agent`)
       * google_guest_compat_manager
       * gce_metadata_script_runner
       * gce_compat_metadata_script_runner (from `cmd/metadata_script_runner_compat`)
       * ggactl_plugin (and the ggactl_plugin_cleanup alias)
       * core_plugin (which is installed at /usr/lib/google/guest_agent/core_plugin)

The `guest-agent` repo delegates all the plugin manager functionality to the new
`google-guest-agent` repo, so it has to be _inside_ the source pkg (as we can't
fetch it during build because the LP builders don't have network access)

The 2 repos happened to share a tag at 20260819.00 the first time but we shouldn't
count on that always being the case - we should treat them as 2 independently versioned
things that just happen to be bundled together.

Concatenated version number
===========================

Because the repos are tagged independently there's no single upstream tag to
use as the pkg version, so `d/watch` uses `uscan`'s group policy on both
stanzas. `uscan` tracks each repo at its own tag and joins the pair with a `+~`:

  <classic tag>+~<plugin manager tag>

e.g. `20260819.00+~20260820.00` for classic tag `20260819.00` plus plugin manager
tag `20260820.00`. Both orig tarballs are then named after that composite version
number, so whichever repo moved is always visible in the version and neither tag
can be silently mistaken for the other.

N.B: `uscan`'s "group" builds the composite unconditionally, so even while the 2
repos share a tag the version still reads `20260819.00+~20260819.00`. It's
ugly but at least it's honest and explicit. It also prepares us now for the
new version format in advance (and doesn't surprise us the first time Google
diverge them)

`+~` sorts the way we want it to which is worth knowing should we ever need to
go back to the plain old single version (all of these pass `dpkg --compare-versions`):

  20260819.00 << 20260819.00+~20260819.00 << 20260819.00+~20260820.00 << 20260820.00

Updating to a new upstream version
==================================

Both tarballs are handled by `uscan`, so the usual workflow still applies:

  uscan --verbose

which gives:

  google-guest-agent_<composite>.orig.tar.gz
  google-guest-agent_<composite>.orig-google-guest-agent.tar.gz

N.B. the _filenames_ use this composite version number, but the directory
_inside_ each tarball still use the repo's own tag. I.e.
`google-guest-agent_20260819.00+~20260820.00.orig.tar.gz` unpacks to
`guest-agent-20260819.00/` `dpkg-source` doesn't care but it may
trip you up when re-vendoring by hand (see below)

The component tarball doesn't need repacking by hand, and doesn't need pinning
to a bare git commit hash: upstream now actually tags the plugin manager repo
and ships the generated *.pb.go files, so neither `protoc` nor the
`proto_deps/` clones from `build/Makefile.gobin` are needed to build the pkg,
thankfully

Adding the right tag into each set of binaries
==============================================

Most of the main packages in both upstream repos have a `main.version` variable
that we set at build time with `-X` (`gce_workload_cert_refresh` and `ggactl_plugin`
don't have one, so the `-X` is silent no-op for those). Giving both repos the composite
would make each one report the _other_ repo's tag as well, so `d/rules` pulls in
`/usr/share/dpkg/pkg-info.mk` and splits `DEB_VERSION_UPSTREAM` apart on `+~`:

  CLASSIC_UPSTREAM := $(firstword $(subst +~, ,$(DEB_VERSION_UPSTREAM)))
  ADDON_UPSTREAM := $(lastword $(subst +~, ,$(DEB_VERSION_UPSTREAM)))

`VERSION` (classic, used via `CLASSIC_LDFLAGS`) and `ADDON_VERSION` (plugin
manager, used via `ADDON_LDFLAGS`) then get the debian revision stuck back on
the end, so a binary identifies the exact pkg build it came from rather than
just the upstream tag. When there's no `+~` in the version both halves collapse
to the same string and the whole thing is a no-op

To check what actually landed in a built binary:

  strings -a /usr/lib/google/guest_agent/core_plugin | grep -E '^20[0-9]{6}\.'

N.B. `go version -m <binary> | grep ldflags` used to be the way to check this but
`d/rules` now passes `-trimpath` (so the LP builder path doesn't get baked into
the binaries) and golang deliberately leaves `-ldflags` out of the recorded
build settings whenever it's set

The two vendored golang dep trees
=================================

Each repo has its own `go.mod` (and therefore its own vendor tree):

  * guest-agent --> debian/extra/vendor/
  * google-guest-agent --> debian/extra/vendor-google-guest-agent/vendor/

`d/rules` copies them into place during `override_dh_auto_configure` as usual
(`./vendor/` and `./google-guest-agent/vendor/` respectively)

N.B. the second tree _must_ land as `google-guest-agent/vendor/modules.txt`
If you end up with `.../vendor/vendor/modules.txt` golang will blow up with an
"inconsistent vendoring" error

To regenerate both trees:

  export GOTOOLCHAIN=local
  export PATH=/usr/lib/go-1.26/bin:$PATH

  # 1. guest-agent (mind the directory name)
  tar xf ../google-guest-agent_<COMPOSITE_VERSION_NUMBER>.orig.tar.gz
  cd guest-agent-<"classic"-tag>
  go mod download && go mod vendor
  mv vendor <pkgdir>/debian/extra/vendor

  # 2. google-guest-agent (mind the name again...)
  tar xf ../google-guest-agent_<COMPOSITE_VERSION_NUMBER>.orig-google-guest-agent.tar.gz
  cd google-guest-agent-<new-plugin-manager-tag>
  go mod download && go mod vendor
  mv vendor <pkgdir>/debian/extra/vendor-google-guest-agent/vendor

and check `d/source/include-binaries` (see below)

Toolchain selection
===================

Both `go.mod` files now have a `toolchain` directive with a golang release that
_might be_ newer than the archive's. golang will try to download that which just dies
in LP, so `d/rules` deliberately sets:

  export GOTOOLCHAIN := local

(the `go` directives do still have to be satisfied by the archive's default golang-go though of course)

Binary blobs in the vendor trees
================================

`dpkg-source` rejects binary files inside `debian.tar.*` unless they're listed in
`d/source/include-binaries`. Both vendor trees now have `protobuf`'s pre-compiled
edition defaults:

  .../vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb

If a re-vendoring pulls in new binary files `dpkg-source` will shout. Just add
them to `d/source/include-binaries`

Where the plugin manager binaries get built
===========================================

`d/rules` builds the component's binaries into `_build/addon-bin/` rather than
into `./google-guest-agent/cmd/*/`. That keeps the unpacked source tree
pristine (so a second `debian/rules build` and/or a `dpkg-source` rebuild doesn't
report random changes against the upstream tree)

`systemd` unit files
====================

The plugin manager is the entry point on _new_ installs: `d/rules` enables and
starts `google-guest-agent-manager.service` and `google-guest-compat-manager.service`,
whereas the legacy `google-guest-agent.service` and `gce-workload-cert-refresh.timer`
are shipped but not enabled. `d/google-guest-agent.postinst` stops and disables those 2
legacy units when upgrading from a "pre-plugin manager" pkg version, and seeds
`/etc/google-guest-agent/core-plugin-enabled` with "true" (without clobbering the user's
choice)

N.B. the plugin manager repo ships its own copies of 3 of the units
under `google-guest-agent/build/configs/usr/lib/systemd/system/`, and they're
the generic upstream ones which are wrong for Ubuntu. They call `google_metadata_script_runner`
rather than `google_metadata_script_runner_adapt`, and order themselves after
`google-guest-agent.service` rather than `google-guest-agent-manager.service`.
`d/install` globs `*.service`, which isn't recursive and so only picks up the
top-level "classic" ones. This is all on purpose, please don't change it to `**` or a
`find` command
