contrib/git-changes-action/main.go
// Package main provides the entrypoint for the action
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"sort"
"strings"
"time"
moduledetector "github.com/synapsecns/sanguine/contrib/git-changes-action/detector/module"
packagedetector "github.com/synapsecns/sanguine/contrib/git-changes-action/detector/package"
"github.com/synapsecns/sanguine/contrib/git-changes-action/detector/tree"
"github.com/sethvargo/go-githubactions"
"github.com/synapsecns/sanguine/contrib/git-changes-action/detector/git"
)
const defaultTimeout = "1m"
func main() {
token := githubactions.GetInput("github_token")
dependencyLevelResolution := githubactions.GetInput("dependencyLevelResolution")
workingDirectory, err := os.Getwd()
if err != nil {
panic(err)
}
ref := githubactions.GetInput("ref")
base := githubactions.GetInput("base")
timeout, err := getTimeout()
if err != nil {
panic(fmt.Errorf("failed to parse timeout: %w", err))
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
ct, err := git.GetChangeTree(ctx, workingDirectory, ref, token, base)
if err != nil {
panic(err)
}
noDepChanged, noDepUnchanged, _, err := outputModuleChanges(workingDirectory, ct, false, dependencyLevelResolution)
if err != nil {
panic(err)
}
depChanged, depUnchanged, allModules, err := outputModuleChanges(workingDirectory, ct, true, dependencyLevelResolution)
if err != nil {
panic(err)
}
githubactions.SetOutput("changed_modules", noDepChanged)
githubactions.SetOutput("unchanged_modules", noDepUnchanged)
githubactions.SetOutput("changed_modules_deps", depChanged)
githubactions.SetOutput("unchanged_modules_deps", depUnchanged)
githubactions.SetOutput("all_modules", allModules)
}
// outputModuleChanges outputs the changed modules.
// this wraps detector.DetectChangedModules and handles the output formatting to be parsable by github actions.
// the final output is a json array of strings.
func outputModuleChanges(workingDirectory string, ct tree.Tree, includeDeps bool, dependencyLevelResolution string) (changedJSON string, unchangedJSON string, allModulesJSON string, err error) {
var modules map[string]bool
if dependencyLevelResolution == "packages" {
modules, err = packagedetector.DetectChangedModules(workingDirectory, ct, includeDeps)
} else {
modules, err = moduledetector.DetectChangedModules(workingDirectory, ct, includeDeps)
}
if err != nil {
return changedJSON, unchangedJSON, allModulesJSON, fmt.Errorf("failed to detect changed modules w/ include deps set to %v: %w", includeDeps, err)
}
var changedModules, unchangedModules, allModules []string
for module, changed := range modules {
modName := strings.TrimPrefix(module, "./")
allModules = append(allModules, modName)
if changed {
changedModules = append(changedModules, modName)
} else {
unchangedModules = append(unchangedModules, modName)
}
}
sort.Strings(changedModules)
sort.Strings(unchangedModules)
sort.Strings(allModules)
marshalledChanged, err := json.Marshal(changedModules)
if err != nil {
return changedJSON, unchangedJSON, allModulesJSON, fmt.Errorf("failed to marshall changed module json w/ include deps set to %v: %w", includeDeps, err)
}
marshalledUnchanged, err := json.Marshal(unchangedModules)
if err != nil {
return changedJSON, unchangedJSON, allModulesJSON, fmt.Errorf("failed to marshall unchanged module json w/ include deps set to %v: %w", includeDeps, err)
}
marshalledAll, err := json.Marshal(allModules)
if err != nil {
return changedJSON, unchangedJSON, allModulesJSON, fmt.Errorf("failed to marshall all modules json w/ include deps set to %v: %w", includeDeps, err)
}
return string(marshalledChanged), string(marshalledUnchanged), string(marshalledAll), nil
}
// getTimeout gets the timeout setting. If it is not set, it defaults to 1 minute.
// Errors if the timeout is not a valid duration.
func getTimeout() (timeout time.Duration, err error) {
rawTimeout := githubactions.GetInput("timeout")
if rawTimeout == "" {
rawTimeout = defaultTimeout
}
timeout, err = time.ParseDuration(rawTimeout)
if err != nil {
return 0, fmt.Errorf("failed to parse timeout: %w", err)
}
return timeout, nil
}