diff --git a/.github/workflows/clean.yml b/.github/workflows/clean.yml new file mode 100644 index 000000000000..0025a4fd09f5 --- /dev/null +++ b/.github/workflows/clean.yml @@ -0,0 +1,26 @@ +name: clean old packages +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +jobs: + scan-old-package: + runs-on: ubuntu-latest + + # disable for now + if: false + + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.20" + - name: Install dependencies + run: cd tools; go get ./cleantool + - name: Scan old package versions and store the version id to env + env: + ROBOT_TOKEN: ${{ secrets.ROBOT_TOKEN }} + run: | + cd tools;go run ./cleantool/cleantool.go diff --git a/tools/cleantool/cleantool.go b/tools/cleantool/cleantool.go new file mode 100644 index 000000000000..7242c8b14e8b --- /dev/null +++ b/tools/cleantool/cleantool.go @@ -0,0 +1,92 @@ +// Copyright 2021 FerretDB 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 ( + "context" + "fmt" + "log" + "os" + "strings" + "time" + + "github.com/google/go-github/v41/github" + "golang.org/x/oauth2" +) + +// if the most recent update time of the package was 90 days ago, then mark it as +// stale. +func isPackageToBeClean(p *github.PackageVersion) bool { + daysBack := 90 + toBeClean := false + + if time.Now().After(p.UpdatedAt.Add(time.Duration(daysBack) * 24 * time.Hour)) { + log.Printf("Stale version id: %v , recent update was at %s", p.GetID(), p.UpdatedAt) + + toBeClean = true + } else { + log.Printf("Skip version id: %v , recent update was at %s", p.GetID(), p.UpdatedAt) + } + + return toBeClean +} + +func main() { + ctx := context.Background() + tokenName := "ROBOT_TOKEN" + token := os.Getenv(tokenName) + + if token == "" { + log.Fatalf("env variable %v is not found, please set it before run it", tokenName) + } + + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: token}, + ) + tc := oauth2.NewClient(ctx, ts) + client := github.NewClient(tc) + packageType := "container" + packageName := "ferretdb-dev" + orgName := "FerretDB" + pageSize := 100 + pageIndex := 1 + + var versions []string + + for { + listOption := github.ListOptions{Page: pageIndex, PerPage: pageSize} + packageListOption := github.PackageListOptions{ListOptions: listOption} + packages, _, err := client.Organizations.PackageGetAllVersions(ctx, orgName, packageType, packageName, &packageListOption) + if err != nil { + log.Printf("Failed to get versions for page %d", pageIndex) + } + + for _, v := range packages { + if isPackageToBeClean(v) { + versions = append(versions, fmt.Sprintf("%v", v.GetID())) + } + } + + if len(packages) < pageSize { + log.Printf("Come to the last page (page %d)", pageIndex) + break + } + + pageIndex++ + } + + staleVersions := strings.Join(versions, ", ") + log.Printf("Found %d stale versions: %v", len(versions), staleVersions) +} diff --git a/tools/go.mod b/tools/go.mod index fff345b4102e..5fa8ea3382e1 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -5,12 +5,14 @@ go 1.20 require ( github.com/BurntSushi/go-sumtype v0.0.0-20221020234012-480526a59796 github.com/go-task/task/v3 v3.24.0 + github.com/google/go-github/v41 v41.0.0 github.com/goreleaser/nfpm/v2 v2.28.0 github.com/quasilyte/go-consistent v0.0.0-20220429160651-4e46040fbc82 github.com/reviewdog/reviewdog v0.14.1 github.com/stretchr/testify v1.8.2 + golang.org/x/oauth2 v0.8.0 golang.org/x/perf v0.0.0-20230427221525-d343f6398b76 - golang.org/x/tools v0.9.0 + golang.org/x/tools v0.9.1 golang.org/x/vuln v0.1.0 mvdan.cc/gofumpt v0.5.0 ) @@ -49,7 +51,6 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-github/v39 v39.2.0 // indirect - github.com/google/go-github/v41 v41.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/gax-go/v2 v2.3.0 // indirect @@ -103,7 +104,6 @@ require ( golang.org/x/exp v0.0.0-20230212135524-a684f29349b6 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect - golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect golang.org/x/sync v0.2.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/term v0.8.0 // indirect diff --git a/tools/go.sum b/tools/go.sum index cfb418593be7..98819e554391 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -601,8 +601,8 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/perf v0.0.0-20230427221525-d343f6398b76 h1:cPGZx8Liyx5Pq/yX80/6WMKe2yidT0xvVCQBOGa8WHU= golang.org/x/perf v0.0.0-20230427221525-d343f6398b76/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc= @@ -756,8 +756,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.9.0 h1:CtBMYmb33qYal6XpayZzNXlyK/3FpZV8bDq4CZo57b8= -golang.org/x/tools v0.9.0/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/vuln v0.1.0 h1:9GRdj6wAIkDrsMevuolY+SXERPjQPp2P1ysYA0jpZe0= golang.org/x/vuln v0.1.0/go.mod h1:/YuzZYjGbwB8y19CisAppfyw3uTZnuCz3r+qgx/QRzU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=