-
-
Notifications
You must be signed in to change notification settings - Fork 657
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
e533151
commit 70a51d8
Showing
27 changed files
with
1,640 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,26 @@ | ||
name: go.mod check | ||
|
||
on: | ||
workflow_dispatch: | ||
push: | ||
branches: | ||
- main | ||
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 run main.go check |
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,138 @@ | ||
# gomod-sync | ||
|
||
Utility tool to check and update the Go version specified in the `go.mod` files of all exercises. | ||
It works by specifying the desired Go version for all the `go.mod` files to be in. The `check` command | ||
will verify if all `go.mod` files are in the desired version and the `update` command will update all | ||
`go.mod` files to have the desired Go version. | ||
|
||
Some exercises must have its `go.mod` specify a Go version that is different from the other exercise's `go.mod`. | ||
This is supported by the `exceptions` key of the configuration file, where an entry must exist for each exercise | ||
that must not have the default version. | ||
|
||
## Installing | ||
|
||
### Compiling locally | ||
|
||
```console | ||
cd gomod-sync | ||
go build | ||
``` | ||
|
||
This will create an executable `gomod-sync` (`gomod-sync.exe` in windows) in the current directory | ||
that you can run to execute the program. | ||
|
||
### Running without compiling | ||
|
||
```console | ||
cd gomod-sync | ||
go run main.go [command] [flags] | ||
``` | ||
|
||
### Running the tests | ||
|
||
```console | ||
cd gomod-sync | ||
go test ./... | ||
``` | ||
|
||
## Usage | ||
|
||
``` | ||
gomod-sync command [flags] | ||
Available Commands: | ||
check Checks if all go.mod files are in the target version | ||
completion generate the autocompletion script for the specified shell | ||
help Help about any command | ||
list List go.mod files and the Go version they specify | ||
update Updates go.mod files to the target version | ||
``` | ||
|
||
## 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 | ||
|
||
## 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. | ||
Using this flag will override the version specified in the config file. | ||
|
||
- `-h, --help` | ||
|
||
help for gomod-sync | ||
|
||
|
||
## 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. If the flag is omitted, a file `config.json` | ||
in the current directory will be tried. | ||
|
||
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`. | ||
Specifying the `-v, --goversion` flag overrides the default version specified in this file. | ||
|
||
## Examples | ||
|
||
|
||
* Check if all `go.mod` files of exercises in the `../exercises` folder have the default version | ||
specified in the `config.json` file: | ||
|
||
* `gomod-sync check` | ||
|
||
* Check if all `go.mod` files of exercises in the `exercises` folder have the `1.16` Go version: | ||
|
||
* `gomod-sync check --goversion 1.16 --exercises ./exercises` | ||
|
||
* Update all `go.mod` files of exercises in the `exercises` folder have the `1.16` Go version: | ||
|
||
* `gomod-sync update --goversion 1.16 --exercises ./exercises` | ||
|
||
* Update all `go.mod` files, using a config file to specify the versions of exercises: | ||
|
||
* `gomod-sync update --config a_dir/config.json --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,52 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/exercism/go/gomod-sync/gomod" | ||
"github.com/logrusorgru/aurora/v3" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
rootCmd.AddCommand(checkCmd) | ||
} | ||
|
||
var checkCmd = &cobra.Command{ | ||
SilenceErrors: true, | ||
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.Println(aurora.Red(fmt.Sprintf("%v has version %s, but %s expected - FAIL", file.Path, file.GoVersion, expectedVersion))) | ||
faultyFiles = append(faultyFiles, faultyFile{Info: file, ExpectedVersion: expectedVersion}) | ||
} else { | ||
fmt.Println(aurora.Green(fmt.Sprintf("%v has version %s as expected - OK", file.Path, file.GoVersion))) | ||
} | ||
} | ||
|
||
if len(faultyFiles) > 0 { | ||
fmt.Println(aurora.Red(fmt.Sprintf("The following %d go.mod file(s) do not have the correct version set:", len(faultyFiles)))) | ||
for _, file := range faultyFiles { | ||
fmt.Println(aurora.Red(fmt.Sprintf("\t%v has version %s, but %s expected", 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,25 @@ | ||
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) | ||
} | ||
|
||
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,82 @@ | ||
package config_test | ||
|
||
import ( | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/exercism/go/gomod-sync/cmd/config" | ||
) | ||
|
||
func TestLoad(t *testing.T) { | ||
tests := []struct { | ||
Name string | ||
Path string | ||
Expected config.VersionConfig | ||
ExpectError bool | ||
}{ | ||
{ | ||
Name: "Loading non-existent config", | ||
Path: filepath.Join("..", "..", "testdata", "non_existent.json"), | ||
Expected: config.VersionConfig{}, | ||
ExpectError: true, | ||
}, | ||
{ | ||
Name: "Loading non-existent config", | ||
Path: filepath.Join("..", "..", "testdata", "version_config_no_exceptions.json"), | ||
Expected: config.VersionConfig{ | ||
Default: "1.16", | ||
}, | ||
ExpectError: false, | ||
}, | ||
{ | ||
Name: "Loading config with 1 exception", | ||
Path: filepath.Join("..", "..", "testdata", "version_config_one_exception.json"), | ||
Expected: config.VersionConfig{ | ||
Default: "1.16", | ||
Exceptions: []config.ExerciseVersion{ | ||
{ | ||
Exercise: "exercise01", | ||
Version: "1.17", | ||
}, | ||
}, | ||
}, | ||
ExpectError: false, | ||
}, | ||
{ | ||
Name: "Loading config with 2 exceptions", | ||
Path: filepath.Join("..", "..", "testdata", "version_config_two_exceptions.json"), | ||
Expected: config.VersionConfig{ | ||
Default: "1.16", | ||
Exceptions: []config.ExerciseVersion{ | ||
{ | ||
Exercise: "exercise02", | ||
Version: "1.17", | ||
}, | ||
{ | ||
Exercise: "exercise01", | ||
Version: "1.17", | ||
}, | ||
}, | ||
}, | ||
ExpectError: false, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.Name, func(t *testing.T) { | ||
config, err := config.Load(test.Path) | ||
|
||
if test.ExpectError && err == nil { | ||
t.Fatalf("expected error, but got none") | ||
} | ||
|
||
if !test.ExpectError && err != nil { | ||
t.Fatalf("didn't expect error, but got %v", err) | ||
} | ||
|
||
if !config.Equal(test.Expected) { | ||
t.Fatalf("expected config %+v, but got %+v", test.Expected, config) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.