Skip to content

WIP: gather sunset/deprecation warnings #2173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ jobs:
needs: [prepare-e2e]
runs-on: ubuntu-latest
environment: test
env:
GHCR_REPO: ghcr.io/mongodb/mongodb-atlas-kubernetes-operator-prerelease
GHCR_BUNDLES_REPO: ghcr.io/mongodb/mongodb-atlas-kubernetes-bundles-prerelease
AKO_DEPRECATION_WARNINGS: true
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -230,3 +234,35 @@ jobs:
with:
name: logs
path: output/**
gather-deprecations:
name: Gather Deprecation Warnings
environment: release
needs: [e2e]
runs-on: ubuntu-latest
steps:
- name: Parse logs from e2e tests
run: |
devbox run -- 'make tools/scandeprecation/scandeprecation'
LOGS=$(gh run view ${{ github.run_id }} --log | grep "javaMethod" | ./tools/scandeprecation/scandeprecations)
echo "LOGS=$LOGS" >> $GITHUB_ENV`
- name: Generate GitHub App Token
id: generate_token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.AKO_RELEASER_APP_ID }}
private-key: ${{ secrets.AKO_RELEASER_RSA_KEY }}
owner: ${{ github.repository_owner }}
repositories: |
mongodb-atlas-kubernetes
- name: Create comment from data
if: ${{ ! env.LOGS == '' }}
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate_token.outputs.token }}
script: |
github.rest.issues.createComment({
owner: context.repo.owner,
issue_number: context.issue.number,
repo: context.repo.repo,
body: process.env.LOGS
})
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ deploy/
tools/clean/clean
tools/makejwt/makejwt
tools/metrics/metrics
tools/scandeprecation/scandeprecations

# ignore the ako.siging key local copy
ako.pem
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,6 @@ install-ako-helm:
--set subobjectDeletionProtection=false \
--namespace=$(HELM_AKO_NAMESPACE) --create-namespace
kubectl get crds

tools/scandeprecation/scandeprecation: tools/scandeprecation/*.go
cd tools/scandeprecation && go build .
12 changes: 9 additions & 3 deletions internal/controller/atlas/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"net/http"
"net/url"
"os"
"runtime"
"strings"

Expand All @@ -29,6 +30,7 @@ import (

"github.com/mongodb/mongodb-atlas-kubernetes/v2/api"
akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/deprecation"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/dryrun"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/httputil"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/version"
Expand Down Expand Up @@ -126,7 +128,7 @@ func (p *ProductionProvider) Client(ctx context.Context, creds *Credentials, log
httputil.LoggingTransport(log),
}

transport := p.newDryRunTransport(http.DefaultTransport)
transport := p.newTransport(http.DefaultTransport, log)
httpClient, err := httputil.DecorateClient(&http.Client{Transport: transport}, clientCfg...)
if err != nil {
return nil, err
Expand All @@ -139,7 +141,7 @@ func (p *ProductionProvider) Client(ctx context.Context, creds *Credentials, log

func (p *ProductionProvider) SdkClientSet(ctx context.Context, creds *Credentials, log *zap.SugaredLogger) (*ClientSet, error) {
var transport http.RoundTripper = digest.NewTransport(creds.APIKeys.PublicKey, creds.APIKeys.PrivateKey)
transport = p.newDryRunTransport(transport)
transport = p.newTransport(transport, log)
transport = httputil.NewLoggingTransport(log, false, transport)

httpClient := &http.Client{Transport: transport}
Expand All @@ -157,7 +159,11 @@ func (p *ProductionProvider) SdkClientSet(ctx context.Context, creds *Credential
}, nil
}

func (p *ProductionProvider) newDryRunTransport(delegate http.RoundTripper) http.RoundTripper {
func (p *ProductionProvider) newTransport(delegate http.RoundTripper, log *zap.SugaredLogger) http.RoundTripper {
if os.Getenv("AKO_DEPRECATION_WARNINGS") != "" {
return deprecation.NewLoggingTransport(delegate, log.Desugar())
}

if p.dryRun {
return dryrun.NewDryRunTransport(delegate)
}
Expand Down
51 changes: 51 additions & 0 deletions internal/deprecation/transport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2025 MongoDB Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package deprecation

import (
"net/http"

"go.uber.org/zap"
)

type Transport struct {
delegate http.RoundTripper
logger *zap.Logger
}

func NewLoggingTransport(delegate http.RoundTripper, logger *zap.Logger) *Transport {
return &Transport{
delegate: delegate,
logger: logger.Named("deprecated"),
}
}

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
resp, err := t.delegate.RoundTrip(req)
if resp != nil {
javaMethod := resp.Header.Get("X-Java-Method")
deprecation := resp.Header.Get("Deprecation")
sunset := resp.Header.Get("Sunset")

if deprecation != "" {
t.logger.Warn("deprecation", zap.String("type", "deprecation"), zap.String("date", deprecation), zap.String("javaMethod", javaMethod), zap.String("path", req.URL.Path), zap.String("method", req.Method))
}

if sunset != "" {
t.logger.Warn("sunset", zap.String("type", "sunset"), zap.String("date", sunset), zap.String("javaMethod", javaMethod), zap.String("path", req.URL.Path), zap.String("method", req.Method))
}
}
return resp, err
}
7 changes: 7 additions & 0 deletions tools/scandeprecation/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module tools/scandeprecations

go 1.24.4

require go.uber.org/zap v1.27.0

require go.uber.org/multierr v1.10.0 // indirect
14 changes: 14 additions & 0 deletions tools/scandeprecation/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
90 changes: 90 additions & 0 deletions tools/scandeprecation/scan_deprecations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2025 MongoDB Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"bufio"
"cmp"
"encoding/json"
"fmt"
"os"
"slices"
"strings"

"go.uber.org/zap"
)

type DeprecationResponse struct {
Type string `json:"type"`
Date string `json:"date"`
JavaMethod string `json:"javaMethod"`
}

func main() {
l, err := zap.NewProduction()
if err != nil {
panic(err)
}
log := l.Sugar()

// Take input from stdin (pipe from GitHub CLI)
scanner := bufio.NewScanner(os.Stdin)
var responses []DeprecationResponse
var out strings.Builder
// Markdown table header for GH Comment
out.WriteString("|Type|Java Method|Date|\n|------|------|------|\n")

for scanner.Scan() {
example := scanner.Text()
// Non-JSON logs mean we split by tabs
split := strings.Split(example, "\t")

// Last element is the JSON "body" of the log line
example = split[len(split)-1]

res := DeprecationResponse{}
err = json.Unmarshal([]byte(example), &res)
if err != nil {
log.Warn("failed to unmarshal JSON", zap.Error(err))
continue
}
responses = append(responses, res)
}

// Quit out if there is no deprecations logged
if len(responses) == 0 {
os.Exit(0)
}

// Sort & Compact to remove duplicates
slices.SortFunc(responses, func(a, b DeprecationResponse) int {
if a.JavaMethod != b.JavaMethod {
return cmp.Compare(a.JavaMethod, b.JavaMethod)
}
if a.Type != b.Type {
return cmp.Compare(a.Type, b.Type)
}
return cmp.Compare(a.Date, b.Date)
})
responses = slices.Compact(responses)

// Build the Markdown table
for _, res := range responses {
out.WriteString(res.Type + "|" + res.JavaMethod + "|" + res.Date + "|\n")
}

// Print to stdout
fmt.Println(out.String())
}
Loading