blob: ca0e8b2b400c7ef63a5fb8a7a74e38b7d1832a3d [file] [log] [blame]
// Copyright 2020 Google Inc. All Rights Reserved.
//
// 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.
// This file contains the CLI application for COS Changelog.
// Project information available at go/cos-changelog
//
// This application is responsible for:
// 1. Accepting user input and creating the authenticator object used for
// queries
// 2. Calling function in the Changelog package, converting the output
// to json, and writing the result into a file
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"time"
"cos.googlesource.com/cos/tools/src/pkg/changelog"
"github.com/google/martian/log"
"github.com/urfave/cli/v2"
"go.chromium.org/luci/auth"
"go.chromium.org/luci/common/api/gerrit"
"go.chromium.org/luci/hardcoded/chromeinfra"
)
// Default Manifest location
const (
cosInstanceURL string = "cos.googlesource.com"
defaultManifestRepo string = "cos/manifest-snapshots"
)
func getAuthenticator() *auth.Authenticator {
opts := chromeinfra.DefaultAuthOptions()
opts.Scopes = []string{gerrit.OAuthScope, auth.OAuthScopeEmail}
return auth.NewAuthenticator(context.Background(), auth.InteractiveLogin, opts)
}
func writeChangelogAsJSON(source string, target string, changes map[string][]*changelog.Commit) error {
jsonData, err := json.MarshalIndent(changes, "", " ")
if err != nil {
return fmt.Errorf("writeChangelogAsJSON: Error marshalling changelog from: %s to: %s\n%v", source, target, err)
}
fileName := fmt.Sprintf("%s -> %s.json", source, target)
if err = ioutil.WriteFile(fileName, jsonData, 0644); err != nil {
return fmt.Errorf("writeChangelogAsJSON: Error writing changelog to file: %s\n%v", fileName, err)
}
return nil
}
func generateChangelog(source, target, instance, manifestRepo string) {
start := time.Now()
authenticator := getAuthenticator()
sourceToTargetChanges, targetToSourceChanges, err := changelog.Changelog(authenticator, source, target, instance, manifestRepo)
if err != nil {
log.Infof("generateChangelog: error retrieving changelog between builds %s and %s on GoB instance: %s with manifest repository: %s\n%v\n",
source, target, instance, manifestRepo, err)
os.Exit(1)
}
if err := writeChangelogAsJSON(source, target, sourceToTargetChanges); err != nil {
log.Infof("generateChangelog: error writing first changelog with source: %s and target: %s\n%v\n",
source, target, err)
}
if err := writeChangelogAsJSON(target, source, targetToSourceChanges); err != nil {
log.Infof("generateChangelog: Error writing second changelog with source: %s and target: %s\n%v\n",
target, source, err)
}
log.Infof("Retrieved changelog in %s\n", time.Since(start))
}
func main() {
var instance, manifestRepo string
app := &cli.App{
Name: "changelog",
Usage: "get commits between builds",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "instance",
Value: cosInstanceURL,
Aliases: []string{"i"},
Usage: "GoB `INSTANCE` to use as client",
Destination: &instance,
},
&cli.StringFlag{
Name: "repo",
Value: defaultManifestRepo,
Aliases: []string{"r"},
Usage: "`REPO` containing Manifest file",
Destination: &manifestRepo,
},
},
Action: func(c *cli.Context) error {
if c.NArg() < 2 {
return errors.New("Must specify source and target build number")
}
source := c.Args().Get(0)
target := c.Args().Get(1)
generateChangelog(source, target, instance, manifestRepo)
return nil
},
}
err := app.Run(os.Args)
if err != nil {
log.Infof("main: error running app with arguments: %v:\n%v", os.Args, err)
os.Exit(1)
}
}