chore: Cherry pick#244
Conversation
* ci: publish keyless release attestations * ci: drop nvcr release attestations * ci: narrow release attestation identity * ci: gate attestations to release tags * docs: show immutable release subjects * ci: attest helm chart releases --------- Signed-off-by: AnouarMohamed <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]>
…fter-uninstall (#241) The test left [email protected] freshly installed at chainsaw's automatic CLEANUP, where the new delete-time uninstall finalizer (from #200) must run uninstall pods on every node before releasing the CR. That exceeds chainsaw's default cleanup window, causing "context deadline exceeded". Add a final uninstall-v1 step that flips uninstall.apply=true on the downgraded version and waits for nodeState to empty, so the CR has no installed packages when cleanup deletes it. Signed-off-by: Alex Yuskauskas <[email protected]>
* fix(test): harden core e2e pool against finalizer-cleanup races and improve diagnosability Two changes across the six core-pool chainsaw tests: 1. Add `timeouts.cleanup: 120s` to every core-pool test. Chainsaw's default cleanup window (~30s) is too tight for the project's CR finalizer, which must uncordon nodes, remove labels/annotations, and GC package pods before releasing. Same failure mode that hit downgrade-after-uninstall (PR #241). 2. Add `catch:` blocks to `depends-on` and `simple-skyhook`, mirroring the pattern used by the other four core tests. When these tests flake, CI now captures the Node, Skyhook CR, and package Pods for diagnosis instead of failing without artifacts. No assert logic changes — this is a foundation pass to remove a known flake class and make future flakes diagnosable. Signed-off-by: Alex Yuskauskas <[email protected]> * fix(operator): close StageInterrupt trap when configUpdates signal decays A package whose only interrupt is a `configInterrupts` entry (no top-level `interrupt` block) could get stuck at `StageInterrupt/StateSkipped` permanently when `Status.ConfigUpdates` cleared or never persisted (e.g. due to a 409 on the spec patch). The state machine queried the dynamic `HasInterrupt(config)` signal at four points, and once that signal decayed to false, the package was untouchable: `ProgressSkipped` wouldn't promote it, `NextStage` wouldn't advance it past Interrupt, and `GetComplete`/`IsPackageComplete` wouldn't count it complete. Decouple progression-past-Interrupt from the dynamic signal: - `NextStage`: add `StageInterrupt → StagePostInterrupt` to the no-interrupt default map. The with-interrupt full-replacement map is preserved as-is — PR #200 deliberately omits `StageUninstall → StageApply` from it so with-interrupt uninstalls route via `StageUninstallInterrupt`; collapsing the maps would silently re-enable that transition. - `ProgressSkipped`: drop the `HasInterrupt` gate. The only writer of `StateSkipped` at `StageInterrupt` is `ProcessInterrupt`'s budget-contention branch, which already decided the package needed an interrupt to schedule. Stage alone is sufficient. - `GetComplete`, `IsPackageComplete`: treat `StagePostInterrupt` as unconditionally terminal. The only way to reach it is via the interrupt cycle; gating the terminal check on a signal that can decay is redundant with the entry gate and only becomes load-bearing when the trap fires. Reproducer in `skyhook_types_test.go` exercises all three sites. Surfaced by the `chainsaw/config-skyhook` "update while running" step, which patches the spec mid-flight and concurrently triggers the `HandleMigrations` and `processSkyhooksPerNode` 409 conflict paths — those stretch convergence enough that ConfigUpdates can be lost between the package reaching StageInterrupt and ProgressSkipped firing. Signed-off-by: Alex Yuskauskas <[email protected]> * refactor(operator): GetComplete delegates to IsPackageComplete GetComplete and IsPackageComplete encoded the same terminal-state logic twice. Have GetComplete iterate the spec packages and call IsPackageComplete for each, and move the explanatory comment to IsPackageComplete where the predicate lives. Behavior preserved: the prior implementation iterated node state and filtered to spec packages by name+version match; the new one iterates spec packages and looks them up in node state by unique name (name|version). Same set of packages either way. Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: Alex Yuskauskas <[email protected]>
📝 WalkthroughWalkthroughAdds composite GitHub Actions for cosign signing/verification and OCI digest resolution; rewires agent/operator/release workflows to sign, attest, and verify images/charts. Renames Helm chart to nodewright, updates docs and Chainsaw tests. Modifies operator package state progression and introduces a separate webhook bootstrap manager/lease with concurrent startup. Updates Makefile/deps. Vendors significant golang.org/x/* updates (http2 RFC 9218, idna Unicode-16, sys/unix APIs, tools inspector/packages, text normalization). Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested reviewers
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
Coverage Report for CI Build 26308524881Coverage decreased (-0.03%) to 81.725%Details
Uncovered Changes
Coverage Regressions120 previously-covered lines in 4 files lost coverage.
Coverage Stats
💛 - Coveralls |
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/actions/cosign-verify-release/action.yml:
- Around line 51-57: The certificate identity regexp check must be guarded
against an empty value because bash [[ string =~ $regex ]] treats an empty
pattern as a match-all; update the verification logic that uses
CERTIFICATE_IDENTITY_REGEXP (the env var used for identity verification) to
first ensure CERTIFICATE_IDENTITY_REGEXP is non-empty (e.g., fail with an error
like "certificate-identity-regexp is required" or skip verification explicitly)
before performing the [[ "${SOME_SUBJECT_FIELD}" =~
${CERTIFICATE_IDENTITY_REGEXP} ]] test; reference the existing SUBJECT_NAME and
SUBJECT_DIGEST validation style (the surrounding checks) to implement the new
non-empty guard and error path for CERTIFICATE_IDENTITY_REGEXP.
In @.github/workflows/agent-ci.yaml:
- Around line 229-230: The checkout step ("Checkout repository" using
actions/checkout@v6) currently leaves Git credentials persisted; update that
step to include persist-credentials: false so the action does not expose
credentials to later steps (i.e., add the persist-credentials: false key under
the checkout step configuration).
In @.github/workflows/lint-ci.yaml:
- Line 104: Replace the mutable tag "actions/cache@v4" with the corresponding
full commit SHA for the actions/cache repository (e.g.,
"actions/cache@<full-commit-sha>") so the workflow uses an immutable pinned ref;
locate the "uses: actions/cache@v4" entry in the lint-ci.yaml and update it to
the exact commit SHA for the v4 release you want to track.
In @.github/workflows/operator-ci.yaml:
- Line 364: Replace mutable action tags with immutable commit SHAs for the
third-party actions used in the create-manifest job: change actions/checkout@v6,
docker/login-action@v4, and docker/setup-buildx-action@v4 to the corresponding
full commit SHA pins (e.g., actions/checkout@<commit-sha>,
docker/login-action@<commit-sha>, docker/setup-buildx-action@<commit-sha>) to
prevent supply-chain drift; additionally, for actions/checkout (the
actions/checkout entry) add with: persist-credentials: false if the job does not
require authenticated git operations so credentials are not left in the
workspace.
- Around line 363-364: Update the "Checkout repository" GitHub Actions step that
uses actions/checkout@v6 to disable credential persistence by adding
persist-credentials: false to the step configuration; specifically modify the
step with name "Checkout repository" (uses: actions/checkout@v6) so it includes
persist-credentials: false to avoid leaving the checkout token available for
later steps.
In `@chart/Chart.yaml`:
- Around line 2-11: Replace all hardcoded "skyhook-operator" identifiers in the
kustomize manifests with "nodewright": update kustomization fields namespace:
skyhook-operator-system → namespace: nodewright-system and namePrefix:
skyhook-operator- → namePrefix: nodewright-; change label values for keys
app.kubernetes.io/created-by and part-of from "skyhook-operator" to
"nodewright"; search manager/rbac/webhook/prometheus manifests and sample YAMLs
under operator/config/ for any remaining "skyhook-operator" strings (including
annotations or selector values) and replace them with the corresponding
"nodewright" names so the Helm chart name: nodewright and appVersion/app labels
are consistent across both deployment paths.
In `@chart/templates/_helpers.tpl`:
- Around line 9-24: chart.fullname now omits the conventional release-name
prefix which will change resource names on upgrade; restore backward
compatibility or provide migration guidance: update the template for define
"chart.fullname" to conditionally include .Release.Name (e.g. when a new boolean
value like .Values.preserveReleaseName is true or when detecting an existing
release) while still honoring fullnameOverride and nameOverride, and add
explicit upgrade steps to README.md and CHANGELOG.md (or implement a Helm
pre-upgrade hook) to rename/migrate previously created resources so existing
Deployments/ServiceAccount/PDB/RBAC/cleanup jobs are not orphaned.
In `@docs/release-process.md`:
- Around line 362-363: Replace the stale Helm chart OCI name used in the
examples: update the CHART variable value from
"ghcr.io/nvidia/nodewright/charts/skyhook-operator" to
"ghcr.io/nvidia/nodewright/charts/nodewright" wherever it appears (e.g., the
CHART= lines shown and the other occurrence noted), so verification commands and
tables reference the correct charts/nodewright OCI path.
In `@operator/api/v1alpha1/deployment_policy_webhook_test.go`:
- Around line 339-341: Extract the duplicated timing literals ("10s" and
"100ms") used in the Eventually blocks of deployment_policy_webhook_test.go into
file-level constants (e.g., const defaultEventuallyTimeout = "10s" and const
defaultEventuallyInterval = "100ms") and replace the inline literals in both
Eventually(...) calls (the one using errors.IsNotFound(k8sClient.Get(...), and
the other at lines ~387-389) with these constants so the timeouts are
centralized and not duplicated.
In `@operator/Makefile`:
- Line 56: The Makefile currently sets DOCKER_CMD ?= docker which forces Docker
as the default runtime; change the default to podman by setting DOCKER_CMD ?=
podman so local developer flows use podman while CI can still set
DOCKER_CMD=docker to override; update the DOCKER_CMD default (symbol DOCKER_CMD)
accordingly and ensure no other references need changing so overrides continue
to work.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 64936d53-18a0-4005-8b5a-13dc59d83a96
⛔ Files ignored due to path filters (1)
operator/go.sumis excluded by!**/*.sum
📒 Files selected for processing (205)
.claude/CLAUDE.md.github/actions/cosign-sign-sbom/action.yml.github/actions/cosign-verify-release/action.yml.github/actions/resolve-oci-digest/action.yml.github/workflows/agent-ci.yaml.github/workflows/lint-ci.yaml.github/workflows/operator-ci.yaml.github/workflows/release.ymlREADME.mdchart/Chart.yamlchart/README.mdchart/templates/_helpers.tplchart/values.yamldocs/README.mddocs/designs/webhook-bootstrap-lease.mddocs/release-process.mdk8s-tests/chainsaw/helm/helm-chart-test/assert-no-schedule.yamlk8s-tests/chainsaw/helm/helm-chart-test/assert-scheduled.yamlk8s-tests/chainsaw/helm/helm-node-affinity-test/assert-no-schedule.yamlk8s-tests/chainsaw/helm/helm-node-affinity-test/assert-scheduled.yamlk8s-tests/chainsaw/helm/helm-scale-test/assert-override-resources.yamlk8s-tests/chainsaw/helm/helm-scale-test/assert-scaled-resources.yamlk8s-tests/chainsaw/helm/helm-webhook-test/assert-scheduled.yamlk8s-tests/chainsaw/skyhook/config-skyhook/chainsaw-test.yamlk8s-tests/chainsaw/skyhook/depends-on/chainsaw-test.yamlk8s-tests/chainsaw/skyhook/downgrade-after-uninstall/README.mdk8s-tests/chainsaw/skyhook/downgrade-after-uninstall/chainsaw-test.yamlk8s-tests/chainsaw/skyhook/downgrade-after-uninstall/update-trigger-uninstall-v1.yamlk8s-tests/chainsaw/skyhook/simple-skyhook/chainsaw-test.yamlk8s-tests/chainsaw/skyhook/simple-update-skyhook/chainsaw-test.yamlk8s-tests/chainsaw/skyhook/strict-order/chainsaw-test.yamlk8s-tests/chainsaw/skyhook/validate-packages/chainsaw-test.yamloperator/Makefileoperator/api/v1alpha1/deployment_policy_webhook_test.gooperator/api/v1alpha1/skyhook_types.gooperator/api/v1alpha1/skyhook_types_test.gooperator/cmd/manager/main.gooperator/deps.mkoperator/go.modoperator/internal/controller/webhook_controller.gooperator/vendor/golang.org/x/net/html/iter.gooperator/vendor/golang.org/x/net/html/node.gooperator/vendor/golang.org/x/net/html/nodetype_string.gooperator/vendor/golang.org/x/net/html/parse.gooperator/vendor/golang.org/x/net/html/render.gooperator/vendor/golang.org/x/net/html/token.gooperator/vendor/golang.org/x/net/http2/README.mdoperator/vendor/golang.org/x/net/http2/client_conn_pool.gooperator/vendor/golang.org/x/net/http2/client_priority_go126.gooperator/vendor/golang.org/x/net/http2/client_priority_go127.gooperator/vendor/golang.org/x/net/http2/clientconn.gooperator/vendor/golang.org/x/net/http2/config.gooperator/vendor/golang.org/x/net/http2/frame.gooperator/vendor/golang.org/x/net/http2/http2.gooperator/vendor/golang.org/x/net/http2/server.gooperator/vendor/golang.org/x/net/http2/server_common.gooperator/vendor/golang.org/x/net/http2/server_wrap.gooperator/vendor/golang.org/x/net/http2/transport.gooperator/vendor/golang.org/x/net/http2/transport_common.gooperator/vendor/golang.org/x/net/http2/transport_wrap.gooperator/vendor/golang.org/x/net/http2/writesched.gooperator/vendor/golang.org/x/net/http2/writesched_common.gooperator/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.gooperator/vendor/golang.org/x/net/http2/writesched_priority_rfc9218.gooperator/vendor/golang.org/x/net/http2/writesched_random.gooperator/vendor/golang.org/x/net/http2/writesched_roundrobin.gooperator/vendor/golang.org/x/net/idna/go118.gooperator/vendor/golang.org/x/net/idna/idna.gooperator/vendor/golang.org/x/net/idna/idna9.0.0.gooperator/vendor/golang.org/x/net/idna/pre_go118.gooperator/vendor/golang.org/x/net/idna/punycode.gooperator/vendor/golang.org/x/net/idna/tables10.0.0.gooperator/vendor/golang.org/x/net/idna/tables11.0.0.gooperator/vendor/golang.org/x/net/idna/tables12.0.0.gooperator/vendor/golang.org/x/net/idna/tables13.0.0.gooperator/vendor/golang.org/x/net/idna/tables15.0.0.gooperator/vendor/golang.org/x/net/idna/tables17.0.0.gooperator/vendor/golang.org/x/net/idna/tables9.0.0.gooperator/vendor/golang.org/x/net/idna/trie12.0.0.gooperator/vendor/golang.org/x/net/idna/trie13.0.0.gooperator/vendor/golang.org/x/net/internal/httpcommon/request.gooperator/vendor/golang.org/x/net/internal/httpsfv/httpsfv.gooperator/vendor/golang.org/x/sys/plan9/syscall_plan9.gooperator/vendor/golang.org/x/sys/unix/affinity_linux.gooperator/vendor/golang.org/x/sys/unix/ioctl_signed.gooperator/vendor/golang.org/x/sys/unix/ioctl_unsigned.gooperator/vendor/golang.org/x/sys/unix/mkall.shoperator/vendor/golang.org/x/sys/unix/mkerrors.shoperator/vendor/golang.org/x/sys/unix/readv_unix.gooperator/vendor/golang.org/x/sys/unix/syscall_darwin.gooperator/vendor/golang.org/x/sys/unix/syscall_linux.gooperator/vendor/golang.org/x/sys/unix/syscall_linux_arm.gooperator/vendor/golang.org/x/sys/unix/syscall_linux_arm64.gooperator/vendor/golang.org/x/sys/unix/syscall_linux_loong64.gooperator/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.gooperator/vendor/golang.org/x/sys/unix/syscall_openbsd.gooperator/vendor/golang.org/x/sys/unix/syscall_solaris.gooperator/vendor/golang.org/x/sys/unix/syscall_unix.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_386.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_arm.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_mips.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.gooperator/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.gooperator/vendor/golang.org/x/sys/unix/zsyscall_linux.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.soperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.soperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.soperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.soperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.soperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.soperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.gooperator/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.soperator/vendor/golang.org/x/sys/unix/zsysnum_linux_386.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.gooperator/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_386.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_arm.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_mips.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.gooperator/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.gooperator/vendor/golang.org/x/sys/windows/aliases.gooperator/vendor/golang.org/x/sys/windows/dll_windows.gooperator/vendor/golang.org/x/sys/windows/security_windows.gooperator/vendor/golang.org/x/sys/windows/syscall_windows.gooperator/vendor/golang.org/x/sys/windows/types_windows.gooperator/vendor/golang.org/x/sys/windows/zsyscall_windows.gooperator/vendor/golang.org/x/text/secure/bidirule/bidirule.gooperator/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0.gooperator/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0.gooperator/vendor/golang.org/x/text/unicode/bidi/tables10.0.0.gooperator/vendor/golang.org/x/text/unicode/bidi/tables11.0.0.gooperator/vendor/golang.org/x/text/unicode/bidi/tables12.0.0.gooperator/vendor/golang.org/x/text/unicode/bidi/tables13.0.0.gooperator/vendor/golang.org/x/text/unicode/bidi/tables15.0.0.gooperator/vendor/golang.org/x/text/unicode/bidi/tables17.0.0.gooperator/vendor/golang.org/x/text/unicode/bidi/tables9.0.0.gooperator/vendor/golang.org/x/text/unicode/norm/forminfo.gooperator/vendor/golang.org/x/text/unicode/norm/tables10.0.0.gooperator/vendor/golang.org/x/text/unicode/norm/tables11.0.0.gooperator/vendor/golang.org/x/text/unicode/norm/tables12.0.0.gooperator/vendor/golang.org/x/text/unicode/norm/tables15.0.0.gooperator/vendor/golang.org/x/text/unicode/norm/tables17.0.0.gooperator/vendor/golang.org/x/text/unicode/norm/tables9.0.0.gooperator/vendor/golang.org/x/tools/go/ast/inspector/cursor.gooperator/vendor/golang.org/x/tools/go/ast/inspector/inspector.gooperator/vendor/golang.org/x/tools/go/ast/inspector/iter.gooperator/vendor/golang.org/x/tools/go/packages/golist.gooperator/vendor/golang.org/x/tools/go/packages/packages.gooperator/vendor/golang.org/x/tools/go/types/objectpath/objectpath.gooperator/vendor/golang.org/x/tools/internal/aliases/aliases.gooperator/vendor/golang.org/x/tools/internal/aliases/aliases_go122.gooperator/vendor/golang.org/x/tools/internal/event/core/event.gooperator/vendor/golang.org/x/tools/internal/event/keys/keys.gooperator/vendor/golang.org/x/tools/internal/event/label/label.gooperator/vendor/golang.org/x/tools/internal/gcimporter/iexport.gooperator/vendor/golang.org/x/tools/internal/gcimporter/iimport.gooperator/vendor/golang.org/x/tools/internal/gcimporter/ureader.gooperator/vendor/golang.org/x/tools/internal/gocommand/version.gooperator/vendor/golang.org/x/tools/internal/pkgbits/version.gooperator/vendor/golang.org/x/tools/internal/stdlib/deps.gooperator/vendor/golang.org/x/tools/internal/typeparams/coretype.gooperator/vendor/golang.org/x/tools/internal/typeparams/free.gooperator/vendor/golang.org/x/tools/internal/typesinternal/types.gooperator/vendor/golang.org/x/tools/internal/versions/features.gooperator/vendor/modules.txt
💤 Files with no reviewable changes (11)
- operator/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0.go
- operator/vendor/golang.org/x/net/idna/trie12.0.0.go
- operator/vendor/golang.org/x/net/html/iter.go
- operator/vendor/golang.org/x/net/idna/pre_go118.go
- operator/vendor/golang.org/x/net/idna/trie13.0.0.go
- operator/vendor/golang.org/x/net/idna/go118.go
- operator/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go
- operator/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0.go
- operator/vendor/golang.org/x/sys/unix/syscall_solaris.go
- operator/vendor/golang.org/x/net/idna/idna9.0.0.go
- operator/vendor/golang.org/x/sys/unix/syscall_darwin.go
* ci: publish keyless release attestations (#232) (#240) * ci: publish keyless release attestations * ci: drop nvcr release attestations * ci: narrow release attestation identity * ci: gate attestations to release tags * docs: show immutable release subjects * ci: attest helm chart releases --------- Signed-off-by: AnouarMohamed <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> * chore(docs): update docs around release and location of helm chart (#237) (#239) * fix(test): uninstall downgraded package before cleanup in downgrade-after-uninstall (#241) The test left [email protected] freshly installed at chainsaw's automatic CLEANUP, where the new delete-time uninstall finalizer (from #200) must run uninstall pods on every node before releasing the CR. That exceeds chainsaw's default cleanup window, causing "context deadline exceeded". Add a final uninstall-v1 step that flips uninstall.apply=true on the downgraded version and waits for nodeState to empty, so the CR has no installed packages when cleanup deletes it. Signed-off-by: Alex Yuskauskas <[email protected]> * fix: deadlock in webhook controller when upgrading from old versions (#243) * fix: close StageInterrupt trap + harden core e2e pool (#242) * fix(test): harden core e2e pool against finalizer-cleanup races and improve diagnosability Two changes across the six core-pool chainsaw tests: 1. Add `timeouts.cleanup: 120s` to every core-pool test. Chainsaw's default cleanup window (~30s) is too tight for the project's CR finalizer, which must uncordon nodes, remove labels/annotations, and GC package pods before releasing. Same failure mode that hit downgrade-after-uninstall (PR #241). 2. Add `catch:` blocks to `depends-on` and `simple-skyhook`, mirroring the pattern used by the other four core tests. When these tests flake, CI now captures the Node, Skyhook CR, and package Pods for diagnosis instead of failing without artifacts. No assert logic changes — this is a foundation pass to remove a known flake class and make future flakes diagnosable. Signed-off-by: Alex Yuskauskas <[email protected]> * fix(operator): close StageInterrupt trap when configUpdates signal decays A package whose only interrupt is a `configInterrupts` entry (no top-level `interrupt` block) could get stuck at `StageInterrupt/StateSkipped` permanently when `Status.ConfigUpdates` cleared or never persisted (e.g. due to a 409 on the spec patch). The state machine queried the dynamic `HasInterrupt(config)` signal at four points, and once that signal decayed to false, the package was untouchable: `ProgressSkipped` wouldn't promote it, `NextStage` wouldn't advance it past Interrupt, and `GetComplete`/`IsPackageComplete` wouldn't count it complete. Decouple progression-past-Interrupt from the dynamic signal: - `NextStage`: add `StageInterrupt → StagePostInterrupt` to the no-interrupt default map. The with-interrupt full-replacement map is preserved as-is — PR #200 deliberately omits `StageUninstall → StageApply` from it so with-interrupt uninstalls route via `StageUninstallInterrupt`; collapsing the maps would silently re-enable that transition. - `ProgressSkipped`: drop the `HasInterrupt` gate. The only writer of `StateSkipped` at `StageInterrupt` is `ProcessInterrupt`'s budget-contention branch, which already decided the package needed an interrupt to schedule. Stage alone is sufficient. - `GetComplete`, `IsPackageComplete`: treat `StagePostInterrupt` as unconditionally terminal. The only way to reach it is via the interrupt cycle; gating the terminal check on a signal that can decay is redundant with the entry gate and only becomes load-bearing when the trap fires. Reproducer in `skyhook_types_test.go` exercises all three sites. Surfaced by the `chainsaw/config-skyhook` "update while running" step, which patches the spec mid-flight and concurrently triggers the `HandleMigrations` and `processSkyhooksPerNode` 409 conflict paths — those stretch convergence enough that ConfigUpdates can be lost between the package reaching StageInterrupt and ProgressSkipped firing. Signed-off-by: Alex Yuskauskas <[email protected]> * refactor(operator): GetComplete delegates to IsPackageComplete GetComplete and IsPackageComplete encoded the same terminal-state logic twice. Have GetComplete iterate the spec packages and call IsPackageComplete for each, and move the explanatory comment to IsPackageComplete where the predicate lives. Behavior preserved: the prior implementation iterated node state and filtered to spec packages by name+version match; the new one iterates spec packages and looks them up in node state by unique name (name|version). Same set of packages either way. Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: AnouarMohamed <[email protected]> Signed-off-by: Alex Yuskauskas <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> Co-authored-by: ayuskauskas <[email protected]>
* ci: publish keyless release attestations (#232) (#240) * ci: publish keyless release attestations * ci: drop nvcr release attestations * ci: narrow release attestation identity * ci: gate attestations to release tags * docs: show immutable release subjects * ci: attest helm chart releases --------- Signed-off-by: AnouarMohamed <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> * chore(docs): update docs around release and location of helm chart (#237) (#239) * fix(test): uninstall downgraded package before cleanup in downgrade-after-uninstall (#241) The test left [email protected] freshly installed at chainsaw's automatic CLEANUP, where the new delete-time uninstall finalizer (from #200) must run uninstall pods on every node before releasing the CR. That exceeds chainsaw's default cleanup window, causing "context deadline exceeded". Add a final uninstall-v1 step that flips uninstall.apply=true on the downgraded version and waits for nodeState to empty, so the CR has no installed packages when cleanup deletes it. Signed-off-by: Alex Yuskauskas <[email protected]> * fix: deadlock in webhook controller when upgrading from old versions (#243) * fix: close StageInterrupt trap + harden core e2e pool (#242) * fix(test): harden core e2e pool against finalizer-cleanup races and improve diagnosability Two changes across the six core-pool chainsaw tests: 1. Add `timeouts.cleanup: 120s` to every core-pool test. Chainsaw's default cleanup window (~30s) is too tight for the project's CR finalizer, which must uncordon nodes, remove labels/annotations, and GC package pods before releasing. Same failure mode that hit downgrade-after-uninstall (PR #241). 2. Add `catch:` blocks to `depends-on` and `simple-skyhook`, mirroring the pattern used by the other four core tests. When these tests flake, CI now captures the Node, Skyhook CR, and package Pods for diagnosis instead of failing without artifacts. No assert logic changes — this is a foundation pass to remove a known flake class and make future flakes diagnosable. Signed-off-by: Alex Yuskauskas <[email protected]> * fix(operator): close StageInterrupt trap when configUpdates signal decays A package whose only interrupt is a `configInterrupts` entry (no top-level `interrupt` block) could get stuck at `StageInterrupt/StateSkipped` permanently when `Status.ConfigUpdates` cleared or never persisted (e.g. due to a 409 on the spec patch). The state machine queried the dynamic `HasInterrupt(config)` signal at four points, and once that signal decayed to false, the package was untouchable: `ProgressSkipped` wouldn't promote it, `NextStage` wouldn't advance it past Interrupt, and `GetComplete`/`IsPackageComplete` wouldn't count it complete. Decouple progression-past-Interrupt from the dynamic signal: - `NextStage`: add `StageInterrupt → StagePostInterrupt` to the no-interrupt default map. The with-interrupt full-replacement map is preserved as-is — PR #200 deliberately omits `StageUninstall → StageApply` from it so with-interrupt uninstalls route via `StageUninstallInterrupt`; collapsing the maps would silently re-enable that transition. - `ProgressSkipped`: drop the `HasInterrupt` gate. The only writer of `StateSkipped` at `StageInterrupt` is `ProcessInterrupt`'s budget-contention branch, which already decided the package needed an interrupt to schedule. Stage alone is sufficient. - `GetComplete`, `IsPackageComplete`: treat `StagePostInterrupt` as unconditionally terminal. The only way to reach it is via the interrupt cycle; gating the terminal check on a signal that can decay is redundant with the entry gate and only becomes load-bearing when the trap fires. Reproducer in `skyhook_types_test.go` exercises all three sites. Surfaced by the `chainsaw/config-skyhook` "update while running" step, which patches the spec mid-flight and concurrently triggers the `HandleMigrations` and `processSkyhooksPerNode` 409 conflict paths — those stretch convergence enough that ConfigUpdates can be lost between the package reaching StageInterrupt and ProgressSkipped firing. Signed-off-by: Alex Yuskauskas <[email protected]> * refactor(operator): GetComplete delegates to IsPackageComplete GetComplete and IsPackageComplete encoded the same terminal-state logic twice. Have GetComplete iterate the spec packages and call IsPackageComplete for each, and move the explanatory comment to IsPackageComplete where the predicate lives. Behavior preserved: the prior implementation iterated node state and filtered to spec packages by name+version match; the new one iterates spec packages and looks them up in node state by unique name (name|version). Same set of packages either way. Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: AnouarMohamed <[email protected]> Signed-off-by: Alex Yuskauskas <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> Co-authored-by: ayuskauskas <[email protected]>
* ci: publish keyless release attestations (#232) (#240) * ci: publish keyless release attestations * ci: drop nvcr release attestations * ci: narrow release attestation identity * ci: gate attestations to release tags * docs: show immutable release subjects * ci: attest helm chart releases --------- Signed-off-by: AnouarMohamed <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> * chore(docs): update docs around release and location of helm chart (#237) (#239) * fix(test): uninstall downgraded package before cleanup in downgrade-after-uninstall (#241) The test left [email protected] freshly installed at chainsaw's automatic CLEANUP, where the new delete-time uninstall finalizer (from #200) must run uninstall pods on every node before releasing the CR. That exceeds chainsaw's default cleanup window, causing "context deadline exceeded". Add a final uninstall-v1 step that flips uninstall.apply=true on the downgraded version and waits for nodeState to empty, so the CR has no installed packages when cleanup deletes it. Signed-off-by: Alex Yuskauskas <[email protected]> * fix: deadlock in webhook controller when upgrading from old versions (#243) * fix: close StageInterrupt trap + harden core e2e pool (#242) * fix(test): harden core e2e pool against finalizer-cleanup races and improve diagnosability Two changes across the six core-pool chainsaw tests: 1. Add `timeouts.cleanup: 120s` to every core-pool test. Chainsaw's default cleanup window (~30s) is too tight for the project's CR finalizer, which must uncordon nodes, remove labels/annotations, and GC package pods before releasing. Same failure mode that hit downgrade-after-uninstall (PR #241). 2. Add `catch:` blocks to `depends-on` and `simple-skyhook`, mirroring the pattern used by the other four core tests. When these tests flake, CI now captures the Node, Skyhook CR, and package Pods for diagnosis instead of failing without artifacts. No assert logic changes — this is a foundation pass to remove a known flake class and make future flakes diagnosable. Signed-off-by: Alex Yuskauskas <[email protected]> * fix(operator): close StageInterrupt trap when configUpdates signal decays A package whose only interrupt is a `configInterrupts` entry (no top-level `interrupt` block) could get stuck at `StageInterrupt/StateSkipped` permanently when `Status.ConfigUpdates` cleared or never persisted (e.g. due to a 409 on the spec patch). The state machine queried the dynamic `HasInterrupt(config)` signal at four points, and once that signal decayed to false, the package was untouchable: `ProgressSkipped` wouldn't promote it, `NextStage` wouldn't advance it past Interrupt, and `GetComplete`/`IsPackageComplete` wouldn't count it complete. Decouple progression-past-Interrupt from the dynamic signal: - `NextStage`: add `StageInterrupt → StagePostInterrupt` to the no-interrupt default map. The with-interrupt full-replacement map is preserved as-is — PR #200 deliberately omits `StageUninstall → StageApply` from it so with-interrupt uninstalls route via `StageUninstallInterrupt`; collapsing the maps would silently re-enable that transition. - `ProgressSkipped`: drop the `HasInterrupt` gate. The only writer of `StateSkipped` at `StageInterrupt` is `ProcessInterrupt`'s budget-contention branch, which already decided the package needed an interrupt to schedule. Stage alone is sufficient. - `GetComplete`, `IsPackageComplete`: treat `StagePostInterrupt` as unconditionally terminal. The only way to reach it is via the interrupt cycle; gating the terminal check on a signal that can decay is redundant with the entry gate and only becomes load-bearing when the trap fires. Reproducer in `skyhook_types_test.go` exercises all three sites. Surfaced by the `chainsaw/config-skyhook` "update while running" step, which patches the spec mid-flight and concurrently triggers the `HandleMigrations` and `processSkyhooksPerNode` 409 conflict paths — those stretch convergence enough that ConfigUpdates can be lost between the package reaching StageInterrupt and ProgressSkipped firing. Signed-off-by: Alex Yuskauskas <[email protected]> * refactor(operator): GetComplete delegates to IsPackageComplete GetComplete and IsPackageComplete encoded the same terminal-state logic twice. Have GetComplete iterate the spec packages and call IsPackageComplete for each, and move the explanatory comment to IsPackageComplete where the predicate lives. Behavior preserved: the prior implementation iterated node state and filtered to spec packages by name+version match; the new one iterates spec packages and looks them up in node state by unique name (name|version). Same set of packages either way. Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: AnouarMohamed <[email protected]> Signed-off-by: Alex Yuskauskas <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> Co-authored-by: ayuskauskas <[email protected]>
* ci: publish keyless release attestations (#232) (#240) * ci: publish keyless release attestations * ci: drop nvcr release attestations * ci: narrow release attestation identity * ci: gate attestations to release tags * docs: show immutable release subjects * ci: attest helm chart releases --------- Signed-off-by: AnouarMohamed <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> * chore(docs): update docs around release and location of helm chart (#237) (#239) * fix(test): uninstall downgraded package before cleanup in downgrade-after-uninstall (#241) The test left [email protected] freshly installed at chainsaw's automatic CLEANUP, where the new delete-time uninstall finalizer (from #200) must run uninstall pods on every node before releasing the CR. That exceeds chainsaw's default cleanup window, causing "context deadline exceeded". Add a final uninstall-v1 step that flips uninstall.apply=true on the downgraded version and waits for nodeState to empty, so the CR has no installed packages when cleanup deletes it. Signed-off-by: Alex Yuskauskas <[email protected]> * fix: deadlock in webhook controller when upgrading from old versions (#243) * fix: close StageInterrupt trap + harden core e2e pool (#242) * fix(test): harden core e2e pool against finalizer-cleanup races and improve diagnosability Two changes across the six core-pool chainsaw tests: 1. Add `timeouts.cleanup: 120s` to every core-pool test. Chainsaw's default cleanup window (~30s) is too tight for the project's CR finalizer, which must uncordon nodes, remove labels/annotations, and GC package pods before releasing. Same failure mode that hit downgrade-after-uninstall (PR #241). 2. Add `catch:` blocks to `depends-on` and `simple-skyhook`, mirroring the pattern used by the other four core tests. When these tests flake, CI now captures the Node, Skyhook CR, and package Pods for diagnosis instead of failing without artifacts. No assert logic changes — this is a foundation pass to remove a known flake class and make future flakes diagnosable. Signed-off-by: Alex Yuskauskas <[email protected]> * fix(operator): close StageInterrupt trap when configUpdates signal decays A package whose only interrupt is a `configInterrupts` entry (no top-level `interrupt` block) could get stuck at `StageInterrupt/StateSkipped` permanently when `Status.ConfigUpdates` cleared or never persisted (e.g. due to a 409 on the spec patch). The state machine queried the dynamic `HasInterrupt(config)` signal at four points, and once that signal decayed to false, the package was untouchable: `ProgressSkipped` wouldn't promote it, `NextStage` wouldn't advance it past Interrupt, and `GetComplete`/`IsPackageComplete` wouldn't count it complete. Decouple progression-past-Interrupt from the dynamic signal: - `NextStage`: add `StageInterrupt → StagePostInterrupt` to the no-interrupt default map. The with-interrupt full-replacement map is preserved as-is — PR #200 deliberately omits `StageUninstall → StageApply` from it so with-interrupt uninstalls route via `StageUninstallInterrupt`; collapsing the maps would silently re-enable that transition. - `ProgressSkipped`: drop the `HasInterrupt` gate. The only writer of `StateSkipped` at `StageInterrupt` is `ProcessInterrupt`'s budget-contention branch, which already decided the package needed an interrupt to schedule. Stage alone is sufficient. - `GetComplete`, `IsPackageComplete`: treat `StagePostInterrupt` as unconditionally terminal. The only way to reach it is via the interrupt cycle; gating the terminal check on a signal that can decay is redundant with the entry gate and only becomes load-bearing when the trap fires. Reproducer in `skyhook_types_test.go` exercises all three sites. Surfaced by the `chainsaw/config-skyhook` "update while running" step, which patches the spec mid-flight and concurrently triggers the `HandleMigrations` and `processSkyhooksPerNode` 409 conflict paths — those stretch convergence enough that ConfigUpdates can be lost between the package reaching StageInterrupt and ProgressSkipped firing. Signed-off-by: Alex Yuskauskas <[email protected]> * refactor(operator): GetComplete delegates to IsPackageComplete GetComplete and IsPackageComplete encoded the same terminal-state logic twice. Have GetComplete iterate the spec packages and call IsPackageComplete for each, and move the explanatory comment to IsPackageComplete where the predicate lives. Behavior preserved: the prior implementation iterated node state and filtered to spec packages by name+version match; the new one iterates spec packages and looks them up in node state by unique name (name|version). Same set of packages either way. Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: AnouarMohamed <[email protected]> Signed-off-by: Alex Yuskauskas <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> Co-authored-by: ayuskauskas <[email protected]>
* feat(agent): port enums and steps for agent go rewrite Signed-off-by: Riley Rice <[email protected]> * chore: Cherry pick (#244) * ci: publish keyless release attestations (#232) (#240) * ci: publish keyless release attestations * ci: drop nvcr release attestations * ci: narrow release attestation identity * ci: gate attestations to release tags * docs: show immutable release subjects * ci: attest helm chart releases --------- Signed-off-by: AnouarMohamed <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> * chore(docs): update docs around release and location of helm chart (#237) (#239) * fix(test): uninstall downgraded package before cleanup in downgrade-after-uninstall (#241) The test left [email protected] freshly installed at chainsaw's automatic CLEANUP, where the new delete-time uninstall finalizer (from #200) must run uninstall pods on every node before releasing the CR. That exceeds chainsaw's default cleanup window, causing "context deadline exceeded". Add a final uninstall-v1 step that flips uninstall.apply=true on the downgraded version and waits for nodeState to empty, so the CR has no installed packages when cleanup deletes it. Signed-off-by: Alex Yuskauskas <[email protected]> * fix: deadlock in webhook controller when upgrading from old versions (#243) * fix: close StageInterrupt trap + harden core e2e pool (#242) * fix(test): harden core e2e pool against finalizer-cleanup races and improve diagnosability Two changes across the six core-pool chainsaw tests: 1. Add `timeouts.cleanup: 120s` to every core-pool test. Chainsaw's default cleanup window (~30s) is too tight for the project's CR finalizer, which must uncordon nodes, remove labels/annotations, and GC package pods before releasing. Same failure mode that hit downgrade-after-uninstall (PR #241). 2. Add `catch:` blocks to `depends-on` and `simple-skyhook`, mirroring the pattern used by the other four core tests. When these tests flake, CI now captures the Node, Skyhook CR, and package Pods for diagnosis instead of failing without artifacts. No assert logic changes — this is a foundation pass to remove a known flake class and make future flakes diagnosable. Signed-off-by: Alex Yuskauskas <[email protected]> * fix(operator): close StageInterrupt trap when configUpdates signal decays A package whose only interrupt is a `configInterrupts` entry (no top-level `interrupt` block) could get stuck at `StageInterrupt/StateSkipped` permanently when `Status.ConfigUpdates` cleared or never persisted (e.g. due to a 409 on the spec patch). The state machine queried the dynamic `HasInterrupt(config)` signal at four points, and once that signal decayed to false, the package was untouchable: `ProgressSkipped` wouldn't promote it, `NextStage` wouldn't advance it past Interrupt, and `GetComplete`/`IsPackageComplete` wouldn't count it complete. Decouple progression-past-Interrupt from the dynamic signal: - `NextStage`: add `StageInterrupt → StagePostInterrupt` to the no-interrupt default map. The with-interrupt full-replacement map is preserved as-is — PR #200 deliberately omits `StageUninstall → StageApply` from it so with-interrupt uninstalls route via `StageUninstallInterrupt`; collapsing the maps would silently re-enable that transition. - `ProgressSkipped`: drop the `HasInterrupt` gate. The only writer of `StateSkipped` at `StageInterrupt` is `ProcessInterrupt`'s budget-contention branch, which already decided the package needed an interrupt to schedule. Stage alone is sufficient. - `GetComplete`, `IsPackageComplete`: treat `StagePostInterrupt` as unconditionally terminal. The only way to reach it is via the interrupt cycle; gating the terminal check on a signal that can decay is redundant with the entry gate and only becomes load-bearing when the trap fires. Reproducer in `skyhook_types_test.go` exercises all three sites. Surfaced by the `chainsaw/config-skyhook` "update while running" step, which patches the spec mid-flight and concurrently triggers the `HandleMigrations` and `processSkyhooksPerNode` 409 conflict paths — those stretch convergence enough that ConfigUpdates can be lost between the package reaching StageInterrupt and ProgressSkipped firing. Signed-off-by: Alex Yuskauskas <[email protected]> * refactor(operator): GetComplete delegates to IsPackageComplete GetComplete and IsPackageComplete encoded the same terminal-state logic twice. Have GetComplete iterate the spec packages and call IsPackageComplete for each, and move the explanatory comment to IsPackageComplete where the predicate lives. Behavior preserved: the prior implementation iterated node state and filtered to spec packages by name+version match; the new one iterates spec packages and looks them up in node state by unique name (name|version). Same set of packages either way. Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: Alex Yuskauskas <[email protected]> --------- Signed-off-by: AnouarMohamed <[email protected]> Signed-off-by: Alex Yuskauskas <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> Co-authored-by: ayuskauskas <[email protected]> --------- Signed-off-by: Riley Rice <[email protected]> Signed-off-by: AnouarMohamed <[email protected]> Signed-off-by: Alex Yuskauskas <[email protected]> Co-authored-by: Brian Lockwood <[email protected]> Co-authored-by: Anouar Mohamed <[email protected]> Co-authored-by: ayuskauskas <[email protected]>
Description
git cherry-pick 2dfec98 6d6f126 bdfa3e6