Skip to content

Commit 5acadea

Browse files
committed
Add a Library Manager configuration for linting while indexing releases
Some of Arduino Lint's rules are based on the data in the published Arduino Library Manager index. These allow library maintainers to check compliance with the Library Manager submission or update requirements. Work is now in progress to use Arduino Lint to validate library releases during the generation of the index. In this usage, data from the published index is not relevant, meaning the results from those rules are inaccurate and so downloading the index for the sake of them is a waste. So another configuration mode is needed to to allow the index-based rules to be disabled. Since this mode is of no use to normal users of Arduino Lint, it is enabled via an environment variable so that no unnecessary complexity is added to the standard UI of the tool. The environment variable name is `ARDUINO_LINT_LIBRARY_MANAGER_INDEXING`.
1 parent 406e297 commit 5acadea

File tree

12 files changed

+71
-21
lines changed

12 files changed

+71
-21
lines changed

docs/index.md

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ The `--report-file` flag causes `arduino-lint` to write the JSON output to the s
6565
Additional configuration options intended for internal use or development can be set via environment variables:
6666

6767
- `ARDUINO_LINT_OFFICIAL` - Set to `"true"` to run the checks that only apply to official Arduino projects.
68+
- `ARDUINO_LINT_LIBRARY_MANAGER_INDEXING` - Set to `"true"` to run the checks that apply when adding releases to the
69+
Library Manager index.
6870
- `ARDUINO_LINT_LOG_LEVEL` - Messages with this level and above will be logged.
6971
- Supported values: `trace`, `debug`, `info`, `warn`, `error`, `fatal`, `panic`
7072
- `ARDUINO_LINT_LOG_FORMAT` - The output format for the logs.

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ require (
4848
go.bug.st/relaxed-semver v0.0.0-20190922224835-391e10178d18
4949
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.14.0 // indirect
5050
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 // indirect
51-
golang.org/x/mod v0.4.1 // indirect
51+
golang.org/x/mod v0.4.2 // indirect
5252
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 // indirect
5353
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d // indirect
5454
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect

go.sum

+3-4
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,7 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jK
11821182
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
11831183
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
11841184
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
1185+
golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw=
11851186
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
11861187
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
11871188
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -1191,10 +1192,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
11911192
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
11921193
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
11931194
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
1194-
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
1195-
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
1196-
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
1197-
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
1195+
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
1196+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
11981197
golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
11991198
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
12001199
golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

internal/configuration/configuration.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,24 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
5151

5252
libraryManagerModeString, _ := flags.GetString("library-manager")
5353
if libraryManagerModeString != "" {
54-
customRuleModes[rulemode.LibraryManagerSubmission], customRuleModes[rulemode.LibraryManagerIndexed], err = rulemode.LibraryManagerModeFromString(libraryManagerModeString)
54+
customRuleModes[rulemode.LibraryManagerSubmission], customRuleModes[rulemode.LibraryManagerIndexed], customRuleModes[rulemode.LibraryManagerIndexing], err = rulemode.LibraryManagerModeFromString(libraryManagerModeString)
5555
if err != nil {
5656
return fmt.Errorf("--library-manager flag value %s not valid", libraryManagerModeString)
5757
}
5858
}
5959

60+
if libraryManagerModeString, ok := os.LookupEnv("ARDUINO_LINT_LIBRARY_MANAGER_INDEXING"); ok {
61+
indexing, err := strconv.ParseBool(libraryManagerModeString)
62+
if err != nil {
63+
return fmt.Errorf("ARDUINO_LINT_LIBRARY_MANAGER_INDEXING environment variable value %s not valid", libraryManagerModeString)
64+
}
65+
if indexing {
66+
customRuleModes[rulemode.LibraryManagerSubmission] = false
67+
customRuleModes[rulemode.LibraryManagerIndexed] = false
68+
customRuleModes[rulemode.LibraryManagerIndexing] = true
69+
}
70+
}
71+
6072
if logFormatString, ok := os.LookupEnv("ARDUINO_LINT_LOG_FORMAT"); ok {
6173
logFormat, err := logFormatFromString(logFormatString)
6274
if err != nil {
@@ -124,6 +136,7 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
124136
"output format": OutputFormat(),
125137
"Library Manager submission mode": customRuleModes[rulemode.LibraryManagerSubmission],
126138
"Library Manager update mode": customRuleModes[rulemode.LibraryManagerIndexed],
139+
"Library Manager indexing mode": customRuleModes[rulemode.LibraryManagerIndexing],
127140
"log level": logrus.GetLevel().String(),
128141
"superproject type filter": SuperprojectTypeFilter(),
129142
"recursive": Recursive(),

internal/configuration/configuration_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ func TestInitializeLibraryManager(t *testing.T) {
105105
assert.Nil(t, Initialize(flags, projectPaths))
106106
assert.False(t, customRuleModes[rulemode.LibraryManagerSubmission])
107107
assert.False(t, customRuleModes[rulemode.LibraryManagerIndexed])
108+
109+
os.Setenv("ARDUINO_LINT_LIBRARY_MANAGER_INDEXING", "foo")
110+
assert.Error(t, Initialize(flags, projectPaths))
111+
112+
flags.Set("library-manager", "")
113+
os.Setenv("ARDUINO_LINT_LIBRARY_MANAGER_INDEXING", "true")
114+
assert.Nil(t, Initialize(flags, projectPaths))
115+
assert.False(t, customRuleModes[rulemode.LibraryManagerSubmission])
116+
assert.False(t, customRuleModes[rulemode.LibraryManagerIndexed])
117+
assert.True(t, customRuleModes[rulemode.LibraryManagerIndexing])
108118
}
109119

110120
func TestInitializeLogFormat(t *testing.T) {

internal/configuration/defaults.go

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var defaultRuleModes = map[projecttype.Type]map[rulemode.Type]bool{
3333
rulemode.Permissive: false,
3434
rulemode.LibraryManagerSubmission: false,
3535
rulemode.LibraryManagerIndexed: false,
36+
rulemode.LibraryManagerIndexing: false,
3637
rulemode.Official: false,
3738
},
3839
projecttype.Library: {
@@ -41,6 +42,7 @@ var defaultRuleModes = map[projecttype.Type]map[rulemode.Type]bool{
4142
rulemode.Permissive: false,
4243
rulemode.LibraryManagerSubmission: true,
4344
rulemode.LibraryManagerIndexed: false,
45+
rulemode.LibraryManagerIndexing: false,
4446
rulemode.Official: false,
4547
},
4648
projecttype.Platform: {
@@ -49,6 +51,7 @@ var defaultRuleModes = map[projecttype.Type]map[rulemode.Type]bool{
4951
rulemode.Permissive: false,
5052
rulemode.LibraryManagerSubmission: false,
5153
rulemode.LibraryManagerIndexed: false,
54+
rulemode.LibraryManagerIndexing: false,
5255
rulemode.Official: false,
5356
},
5457
projecttype.PackageIndex: {
@@ -57,6 +60,7 @@ var defaultRuleModes = map[projecttype.Type]map[rulemode.Type]bool{
5760
rulemode.Permissive: false,
5861
rulemode.LibraryManagerSubmission: false,
5962
rulemode.LibraryManagerIndexed: false,
63+
rulemode.LibraryManagerIndexing: false,
6064
rulemode.Official: false,
6165
},
6266
}

internal/configuration/rulemode/rulemode.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const (
3434
Permissive // permissive
3535
LibraryManagerSubmission // submit
3636
LibraryManagerIndexed // update
37+
LibraryManagerIndexing // ARDUINO_LINT_LIBRARY_MANAGER_INDEXING
3738
Official // ARDUINO_LINT_OFFICIAL
3839
Default // default
3940
)
@@ -47,6 +48,7 @@ var Types = map[Type]struct{}{
4748
Permissive: empty,
4849
LibraryManagerSubmission: empty,
4950
LibraryManagerIndexed: empty,
51+
LibraryManagerIndexing: empty,
5052
Official: empty,
5153
Default: empty,
5254
}
@@ -66,16 +68,16 @@ func ComplianceModeFromString(complianceModeString string) (bool, bool, bool, er
6668
}
6769

6870
// LibraryManagerModeFromString parses the --library-manager flag value and returns the corresponding rule mode settings.
69-
func LibraryManagerModeFromString(libraryManagerModeString string) (bool, bool, error) {
71+
func LibraryManagerModeFromString(libraryManagerModeString string) (bool, bool, bool, error) {
7072
switch strings.ToLower(libraryManagerModeString) {
7173
case LibraryManagerSubmission.String():
72-
return true, false, nil
74+
return true, false, false, nil
7375
case LibraryManagerIndexed.String():
74-
return false, true, nil
76+
return false, true, false, nil
7577
case "false":
76-
return false, false, nil
78+
return false, false, false, nil
7779
default:
78-
return false, false, fmt.Errorf("No matching Library Manager mode for string %s", libraryManagerModeString)
80+
return false, false, false, fmt.Errorf("No matching Library Manager mode for string %s", libraryManagerModeString)
7981
}
8082
}
8183

@@ -110,7 +112,7 @@ func Compliance(ruleModes map[Type]bool) string {
110112
// LibraryManager returns the string identifier for the Library Manager configuration mode.
111113
func LibraryManager(ruleModes map[Type]bool) string {
112114
for key, value := range ruleModes {
113-
if value && (key == LibraryManagerSubmission || key == LibraryManagerIndexed) {
115+
if value && (key == LibraryManagerSubmission || key == LibraryManagerIndexed || key == LibraryManagerIndexing) {
114116
return key.String()
115117
}
116118
}

internal/configuration/rulemode/rulemode_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ func TestMode(t *testing.T) {
4040
projecttype.Sketch: {
4141
LibraryManagerSubmission: false,
4242
LibraryManagerIndexed: false,
43+
LibraryManagerIndexing: false,
4344
Official: false,
4445
},
4546
projecttype.Library: {
4647
LibraryManagerSubmission: true,
4748
LibraryManagerIndexed: false,
49+
LibraryManagerIndexing: false,
4850
Official: false,
4951
},
5052
}

internal/configuration/rulemode/type_string.go

+5-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/project/projectdata/library.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"os"
2323

2424
"github.com/arduino/arduino-cli/arduino/libraries"
25+
"github.com/arduino/arduino-lint/internal/configuration"
26+
"github.com/arduino/arduino-lint/internal/configuration/rulemode"
2527
"github.com/arduino/arduino-lint/internal/project"
2628
"github.com/arduino/arduino-lint/internal/project/library/libraryproperties"
2729
"github.com/arduino/arduino-lint/internal/result/feedback"
@@ -56,7 +58,8 @@ func InitializeForLibrary(project project.Type) {
5658
}
5759
}
5860

59-
if libraryManagerIndex == nil { // Only download the Library Manager index once.
61+
// Download the Library Manager index if needed.
62+
if !configuration.RuleModes(project.SuperprojectType)[rulemode.LibraryManagerIndexing] && libraryManagerIndex == nil {
6063
url := "http://downloads.arduino.cc/libraries/library_index.json"
6164
httpResponse, err := http.Get(url)
6265
if err != nil {

internal/rule/ruleconfiguration/ruleconfiguration.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ var configurations = []Type{
134134
EnableModes: []rulemode.Type{rulemode.Default},
135135
InfoModes: nil,
136136
WarningModes: []rulemode.Type{rulemode.Default},
137-
ErrorModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed},
137+
ErrorModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed, rulemode.LibraryManagerIndexing},
138138
RuleFunction: rulefunction.LibraryContainsSymlinks,
139139
},
140140
{
@@ -150,7 +150,7 @@ var configurations = []Type{
150150
EnableModes: []rulemode.Type{rulemode.Default},
151151
InfoModes: nil,
152152
WarningModes: []rulemode.Type{rulemode.Default},
153-
ErrorModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed, rulemode.Strict},
153+
ErrorModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed, rulemode.LibraryManagerIndexing, rulemode.Strict},
154154
RuleFunction: rulefunction.LibraryHasDotDevelopmentFile,
155155
},
156156
{
@@ -163,7 +163,7 @@ var configurations = []Type{
163163
Description: "",
164164
MessageTemplate: ".exe file(s) found: {{.}}. Presence of these files blocks addition to the Library Manager index.",
165165
DisableModes: []rulemode.Type{rulemode.Default},
166-
EnableModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed},
166+
EnableModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed, rulemode.LibraryManagerIndexing},
167167
InfoModes: nil,
168168
WarningModes: nil,
169169
ErrorModes: []rulemode.Type{rulemode.Default},
@@ -262,7 +262,7 @@ var configurations = []Type{
262262
EnableModes: []rulemode.Type{rulemode.Default},
263263
InfoModes: nil,
264264
WarningModes: []rulemode.Type{rulemode.Default},
265-
ErrorModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed, rulemode.Strict},
265+
ErrorModes: []rulemode.Type{rulemode.LibraryManagerSubmission, rulemode.LibraryManagerIndexed, rulemode.LibraryManagerIndexing, rulemode.Strict},
266266
RuleFunction: rulefunction.LibraryPropertiesMissing,
267267
},
268268
{

test/test_all.py

+14
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ def test_library_manager_invalid(run_command):
9595
assert not result.ok
9696

9797

98+
def test_library_manager_indexing(run_command):
99+
result = run_command(
100+
cmd=[test_data_path.joinpath("library-manager", "Update")],
101+
custom_env={"ARDUINO_LINT_LIBRARY_MANAGER_INDEXING": "true"},
102+
)
103+
assert result.ok
104+
105+
result = run_command(
106+
cmd=[test_data_path.joinpath("library-manager", "Update")],
107+
custom_env={"ARDUINO_LINT_LIBRARY_MANAGER_INDEXING": "foo"},
108+
)
109+
assert not result.ok
110+
111+
98112
@pytest.mark.parametrize(
99113
"project_folder, expected_exit_statuses",
100114
[

0 commit comments

Comments
 (0)