-
-
Notifications
You must be signed in to change notification settings - Fork 655
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3d87554
commit 1ca7f2a
Showing
17 changed files
with
1,089 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: go.mod check | ||
|
||
on: | ||
workflow_dispatch: | ||
push: | ||
branches: | ||
- main | ||
- master | ||
pull_request: | ||
|
||
jobs: | ||
check: | ||
name: go.mod check | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: 1.17 | ||
|
||
- name: Check go.mod files | ||
shell: bash | ||
run: | | ||
cd gomod-sync && go build | ||
./gomod-sync check --goversion 1.16 --exercises ../exercises |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
|
||
# Dependency directories (remove the comment below to include it) | ||
# vendor/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# gomod-sync | ||
|
||
Utility tool to check and update `go.mod` versions. | ||
|
||
## Flags | ||
|
||
- `-c, --config config_file` | ||
|
||
path to the JSON configuration file. (default "config.json") | ||
|
||
- `-e, --exercises exercises_path` | ||
|
||
path to the exercises folder. go.mod files will be recursively searched inside this directory. (default "../exercises") | ||
- `-v, --goversion target_version` | ||
|
||
target go version that all go.mod files are expected to have. This will be used to check if the go.mod files are in the expected version in case of the check command, and to update all go.mod files to this version in the case of the update command. | ||
|
||
- `-h, --help` | ||
|
||
help for gomod-sync | ||
|
||
## Commands | ||
|
||
- `gomod-sync check -v target_version [-e exercises_path] [-c config_file]` | ||
|
||
checks if all go.mod files are in the target version | ||
|
||
- `gomod-sync completion` | ||
|
||
generate the autocompletion script for the specified shell | ||
- `gomod-sync help` | ||
|
||
Help about any command | ||
- `gomod-sync list [-e exercises_path]` | ||
|
||
list `go.mod` files and the Go version they specify | ||
- `gomod-sync update -v target_version [-e exercises_path] [-c config_file]` | ||
|
||
updates `go.mod` files to the target version | ||
|
||
## Configuration file | ||
|
||
Besides the `-v, --goversion` flag, it is also possible to specify the expected go versions for the `go.mod` files in a JSON configuration file. | ||
This file can be given to the program with the `-c, --config file` flag. | ||
|
||
With a configuration file, in addition to define a default Go version all exercises' `go.mod` must have, | ||
it's also possible to configure different versions for different exercises. This can be useful if a particular exercise | ||
needs a superior version of Go than the default. | ||
|
||
This an example of such configuration file: | ||
|
||
```json | ||
{ | ||
"default": "1.16", | ||
"exceptions": [ | ||
{ | ||
"exercise": "strain", | ||
"version": "1.18" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
With such configuration, all `go.mod` files will be expected to have the `1.16` version of Go, | ||
except the exercise `strain`, which must have version `1.18` in its `go.mod`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/exercism/go/gomod-sync/gomod" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
rootCmd.AddCommand(checkCmd) | ||
} | ||
|
||
var checkCmd = &cobra.Command{ | ||
Use: "check", | ||
Short: "Checks if all go.mod files are in the target version", | ||
PersistentPreRunE: loadConfig, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
files, err := gomod.Infos(exercisesPathFlag) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
type faultyFile struct { | ||
gomod.Info | ||
ExpectedVersion string | ||
} | ||
|
||
var faultyFiles []faultyFile | ||
for _, file := range files { | ||
expectedVersion := versionConfig.ExerciseExpectedVersion(file.ExerciseSlug) | ||
if file.GoVersion != expectedVersion { | ||
fmt.Fprintf(os.Stderr, "%v has version %s, but %s expected - FAIL\n", file.Path, file.GoVersion, expectedVersion) | ||
faultyFiles = append(faultyFiles, faultyFile{Info: file, ExpectedVersion: expectedVersion}) | ||
} else { | ||
fmt.Printf("%v has version %s as expected - OK\n", file.Path, file.GoVersion) | ||
} | ||
} | ||
|
||
if len(faultyFiles) > 0 { | ||
fmt.Fprintf(os.Stderr, "The following %d go.mod file(s) do not have the correct version set:\n", len(faultyFiles)) | ||
for _, file := range faultyFiles { | ||
fmt.Fprintf(os.Stderr,"\t%v has version %s, but %s expected\n", file.Path, file.GoVersion, file.ExpectedVersion) | ||
} | ||
return fmt.Errorf("%d go.mod file(s) are not in the target version", len(faultyFiles)) | ||
} | ||
|
||
return nil | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package config | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
) | ||
|
||
// Load loads a configuration from a path to a JSON file. | ||
func Load(file string) (VersionConfig, error) { | ||
var config VersionConfig | ||
|
||
f, err := os.Open(file) | ||
if err != nil { | ||
return config, fmt.Errorf("failed to open config file: %v", err) | ||
} | ||
defer f.Close() | ||
|
||
err = json.NewDecoder(f).Decode(&config) | ||
if err != nil { | ||
return config, fmt.Errorf("failed to decode config file: %v", err) | ||
} | ||
|
||
config.exerciseVersionMap = make(map[string]string) | ||
for _, exception := range config.Exceptions { | ||
config.exerciseVersionMap[exception.Exercise] = exception.Version | ||
} | ||
|
||
return config, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package config | ||
|
||
// VersionConfig represents the version configuration | ||
type VersionConfig struct { | ||
// Default version for the go.mod files | ||
Default string `json:"default"` | ||
// List of exercises and their versions that must not have | ||
// the default version. | ||
Exceptions []ExerciseVersion `json:"exceptions"` | ||
// exerciseVersionMap must hold the same information as Exceptions, | ||
// but in map form. This is a mapping of exercise slugs to their versions. | ||
exerciseVersionMap map[string]string | ||
} | ||
|
||
// ExerciseExpectedVersion gives the expected version the go.mod file for | ||
// an exercise should be at. The argument should be the slug of an exercise. | ||
func (vc *VersionConfig) ExerciseExpectedVersion(exercise string) string { | ||
if version, ok := vc.exerciseVersionMap[exercise]; ok { | ||
return version | ||
} | ||
|
||
return vc.Default | ||
} | ||
|
||
// ExerciseVersion represents the version one particular exercise should | ||
// have in its go.mod file | ||
type ExerciseVersion struct { | ||
Exercise string `json:"exercise"` | ||
Version string `json:"version"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/exercism/go/gomod-sync/gomod" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
rootCmd.AddCommand(listCmd) | ||
} | ||
|
||
var listCmd = &cobra.Command{ | ||
Use: "list", | ||
Short: "List go.mod files and the Go version they specify", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
files, err := gomod.Infos(exercisesPathFlag) | ||
if err != nil { | ||
return fmt.Errorf("could not get go.mod information: %w", err) | ||
} | ||
|
||
for _, file := range files { | ||
fmt.Printf("%s => %s\n", file.Path, file.GoVersion) | ||
} | ||
|
||
return nil | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/exercism/go/gomod-sync/cmd/config" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var exercisesPathFlag string | ||
var targetVersionFlag string | ||
var configFileFlag string | ||
var versionConfig config.VersionConfig | ||
|
||
func init() { | ||
rootCmd.PersistentFlags().StringVarP(&exercisesPathFlag, | ||
"exercises", "e", "../exercises", | ||
"path to the exercises folder. go.mod files will "+ | ||
"be recursively searched inside this directory.") | ||
rootCmd.PersistentFlags().StringVarP(&targetVersionFlag, | ||
"goversion", "v", "", | ||
"target go version that all go.mod files are expected to have. "+ | ||
"This will be used to check if the go.mod files are in the expected "+ | ||
"version in case of the check command, and to update all go.mod files to this version "+ | ||
"in the case of the update command.") | ||
rootCmd.PersistentFlags().StringVarP(&configFileFlag, | ||
"config", "c", "config.json", | ||
"path to the JSON configuration file. ") | ||
} | ||
|
||
var rootCmd = &cobra.Command{ | ||
Use: "gomod-sync", | ||
Short: "gomod-sync checks and updates the go version for all go.mod files in a path.", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return nil | ||
}, | ||
} | ||
|
||
func Execute() { | ||
rootCmd.SilenceUsage = true | ||
if err := rootCmd.Execute(); err != nil { | ||
fmt.Fprintln(os.Stderr, err) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
func loadConfig(cmd *cobra.Command, args []string) error { | ||
var err error | ||
|
||
// Load version config | ||
versionConfig, err = config.Load(configFileFlag) | ||
|
||
versionWasGiven := cmd.PersistentFlags().Changed("goversion") | ||
|
||
if err != nil && !versionWasGiven { | ||
return fmt.Errorf("failed to load config file and flag --goversion not present: %v", err) | ||
} | ||
|
||
// Override config default if version passed via flag | ||
if versionWasGiven { | ||
versionConfig.Default = targetVersionFlag | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/exercism/go/gomod-sync/gomod" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
rootCmd.AddCommand(updateCmd) | ||
} | ||
|
||
var updateCmd = &cobra.Command{ | ||
Use: "update", | ||
Short: "Updates go.mod files to the target version", | ||
PersistentPreRunE: loadConfig, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
files, err := gomod.Infos(exercisesPathFlag) | ||
if err != nil { | ||
return fmt.Errorf("could not get go.mod information: %w", err) | ||
} | ||
|
||
for _, file := range files { | ||
expectedVersion := versionConfig.ExerciseExpectedVersion(file.ExerciseSlug) | ||
if file.GoVersion != expectedVersion { | ||
if err := gomod.Update(file.Path, expectedVersion); err != nil { | ||
return fmt.Errorf("failed to update %q: %w", file.Path, err) | ||
} | ||
fmt.Printf("Updated %s: %s => %s\n", file.Path, file.GoVersion, expectedVersion) | ||
} | ||
} | ||
|
||
return nil | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"default": "1.16", | ||
"exceptions": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"default": "1.16", | ||
"exceptions": [ | ||
{ | ||
"exercise": "beer-song", | ||
"version": "1.17" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module github.com/exercism/go/gomod-sync | ||
|
||
go 1.17 | ||
|
||
require ( | ||
github.com/inconshreveable/mousetrap v1.0.0 // indirect | ||
github.com/spf13/cobra v1.2.1 // indirect | ||
github.com/spf13/pflag v1.0.5 // indirect | ||
) |
Oops, something went wrong.