blob: 61a232a197891bb5bc23f4a88f080e06f6a5d154 [file] [log] [blame]
// Copyright 2021 Google LLC
//
// 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 (
"bytes"
"encoding/json"
"fmt"
"io/fs"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)
func main() {
rootDir, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
if len(os.Args) > 1 {
rootDir = os.Args[1]
}
log.Printf("Root dir: %q", rootDir)
var modDirs []string
// Find all external modules
filepath.WalkDir(rootDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.Name() == "internal" {
return filepath.SkipDir
}
if d.Name() == "go.mod" {
modDirs = append(modDirs, filepath.Dir(path))
}
return nil
})
// Find relative sub-module
submodules := map[string]bool{}
for _, dir := range modDirs {
name, err := modName(dir)
if err != nil {
log.Fatalf("unable to lookup mod dir")
}
// Skip non-submodule
if name == "cloud.google.com/go" {
continue
}
name = strings.TrimPrefix(name, "cloud.google.com/go/")
submodules[name] = true
}
c := exec.Command("git", "pull", "--tags")
c.Dir = rootDir
if err := c.Run(); err != nil {
log.Fatalf("unable to pull tags: %v", err)
}
tag, err := latestTag(rootDir)
if err != nil {
log.Fatalf("unable to find tag: %v", err)
}
log.Printf("Latest release: %s", tag)
c = exec.Command("git", "reset", "--hard", tag)
c.Dir = rootDir
if err := c.Run(); err != nil {
log.Fatalf("unable to reset to tag: %v", err)
}
changes, err := gitFilesChanges(rootDir)
if err != nil {
log.Fatalf("unable to get files changed: %v", err)
}
updatedSubmodulesSet := map[string]bool{}
for _, change := range changes {
//TODO(codyoss): This will not work with nested sub-modules. If we add
// those this needs to be updated.
pkg := strings.Split(change, "/")[0]
log.Printf("update to path: %s", pkg)
if submodules[pkg] {
updatedSubmodulesSet[pkg] = true
}
}
updatedSubmodule := []string{}
for mod := range updatedSubmodulesSet {
updatedSubmodule = append(updatedSubmodule, mod)
}
b, err := json.Marshal(updatedSubmodule)
if err != nil {
log.Fatalf("unable to marshal submodules: %v", err)
}
fmt.Printf("::set-output name=submodules::%s", b)
}
func modName(dir string) (string, error) {
c := exec.Command("go", "list", "-m")
c.Dir = dir
b, err := c.Output()
if err != nil {
return "", err
}
b = bytes.TrimSpace(b)
return string(b), nil
}
func latestTag(dir string) (string, error) {
c := exec.Command("git", "rev-list", "--tags", "--max-count=1")
c.Dir = dir
b, err := c.Output()
if err != nil {
return "", err
}
commit := string(bytes.TrimSpace(b))
c = exec.Command("git", "describe", "--tags", commit)
c.Dir = dir
b, err = c.Output()
if err != nil {
return "", err
}
b = bytes.TrimSpace(b)
return string(b), nil
}
func gitFilesChanges(dir string) ([]string, error) {
c := exec.Command("git", "diff", "--name-only", "origin/master")
c.Dir = dir
b, err := c.Output()
if err != nil {
return nil, err
}
b = bytes.TrimSpace(b)
log.Printf("Files changed:\n%s", b)
return strings.Split(string(b), "\n"), nil
}