Skip to content

Commit 3d2ae4c

Browse files
authoredJun 11, 2021
Merge pull request #189 from per1234/package-index-urls
Add rules to check loading of URLs in package index
2 parents e462881 + 6b82e86 commit 3d2ae4c

File tree

13 files changed

+565
-21
lines changed

13 files changed

+565
-21
lines changed
 

‎internal/rule/ruleconfiguration/ruleconfiguration.go

+80
Original file line numberDiff line numberDiff line change
@@ -2921,4 +2921,84 @@ var configurations = []Type{
29212921
ErrorModes: []rulemode.Type{rulemode.Default},
29222922
RuleFunction: rulefunction.PackageIndexFormat,
29232923
},
2924+
{
2925+
ProjectType: projecttype.PackageIndex,
2926+
SuperprojectType: projecttype.All,
2927+
Category: "data",
2928+
Subcategory: "package",
2929+
ID: "ID003",
2930+
Brief: "dead packages[].websiteURL",
2931+
Description: "",
2932+
MessageTemplate: "Unable to load the packages[].websiteURL URL for package(s): {{.}}",
2933+
DisableModes: nil,
2934+
EnableModes: []rulemode.Type{rulemode.Default},
2935+
InfoModes: nil,
2936+
WarningModes: []rulemode.Type{rulemode.Permissive},
2937+
ErrorModes: []rulemode.Type{rulemode.Default},
2938+
RuleFunction: rulefunction.PackageIndexPackagesWebsiteURLDeadLink,
2939+
},
2940+
{
2941+
ProjectType: projecttype.PackageIndex,
2942+
SuperprojectType: projecttype.All,
2943+
Category: "data",
2944+
Subcategory: "package",
2945+
ID: "ID004",
2946+
Brief: "dead packages[].help.online",
2947+
Description: "",
2948+
MessageTemplate: "Unable to load the packages[].help.online URL for package(s): {{.}}",
2949+
DisableModes: nil,
2950+
EnableModes: []rulemode.Type{rulemode.Default},
2951+
InfoModes: nil,
2952+
WarningModes: []rulemode.Type{rulemode.Permissive},
2953+
ErrorModes: []rulemode.Type{rulemode.Default},
2954+
RuleFunction: rulefunction.PackageIndexPackagesHelpOnlineDeadLink,
2955+
},
2956+
{
2957+
ProjectType: projecttype.PackageIndex,
2958+
SuperprojectType: projecttype.All,
2959+
Category: "data",
2960+
Subcategory: "platform",
2961+
ID: "ID005",
2962+
Brief: "dead packages[].platforms[].help.online",
2963+
Description: "",
2964+
MessageTemplate: "Unable to load the packages[].platforms[].help.online URL for platforms(s): {{.}}",
2965+
DisableModes: nil,
2966+
EnableModes: []rulemode.Type{rulemode.Default},
2967+
InfoModes: nil,
2968+
WarningModes: []rulemode.Type{rulemode.Permissive},
2969+
ErrorModes: []rulemode.Type{rulemode.Default},
2970+
RuleFunction: rulefunction.PackageIndexPackagesPlatformsHelpOnlineDeadLink,
2971+
},
2972+
{
2973+
ProjectType: projecttype.PackageIndex,
2974+
SuperprojectType: projecttype.All,
2975+
Category: "data",
2976+
Subcategory: "platform",
2977+
ID: "ID006",
2978+
Brief: "dead packages[].platforms[].url",
2979+
Description: "",
2980+
MessageTemplate: "Unable to load the packages[].platforms[].url URL for platforms(s): {{.}}",
2981+
DisableModes: nil,
2982+
EnableModes: []rulemode.Type{rulemode.Default},
2983+
InfoModes: nil,
2984+
WarningModes: []rulemode.Type{rulemode.Permissive},
2985+
ErrorModes: []rulemode.Type{rulemode.Default},
2986+
RuleFunction: rulefunction.PackageIndexPackagesPlatformsURLDeadLink,
2987+
},
2988+
{
2989+
ProjectType: projecttype.PackageIndex,
2990+
SuperprojectType: projecttype.All,
2991+
Category: "data",
2992+
Subcategory: "tool",
2993+
ID: "ID007",
2994+
Brief: "dead packages[].tools[].systems[].url",
2995+
Description: "",
2996+
MessageTemplate: "Unable to load the packages[].tools[].systems[].url URL for tools(s): {{.}}",
2997+
DisableModes: nil,
2998+
EnableModes: []rulemode.Type{rulemode.Default},
2999+
InfoModes: nil,
3000+
WarningModes: []rulemode.Type{rulemode.Permissive},
3001+
ErrorModes: []rulemode.Type{rulemode.Default},
3002+
RuleFunction: rulefunction.PackageIndexPackagesToolsSystemsURLDeadLink,
3003+
},
29243004
}

‎internal/rule/rulefunction/library.go

+2-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package rulefunction
1919

2020
import (
2121
"fmt"
22-
"net/http"
2322
"os"
2423
"path/filepath"
2524
"regexp"
@@ -1010,17 +1009,12 @@ func LibraryPropertiesUrlFieldDeadLink() (result ruleresult.Type, output string)
10101009
return ruleresult.NotRun, "Field not present"
10111010
}
10121011

1013-
logrus.Tracef("Checking URL: %s", url)
1014-
httpResponse, err := http.Head(url)
1012+
err := checkURL(url)
10151013
if err != nil {
10161014
return ruleresult.Fail, err.Error()
10171015
}
10181016

1019-
if httpResponse.StatusCode == http.StatusOK {
1020-
return ruleresult.Pass, ""
1021-
}
1022-
1023-
return ruleresult.Fail, httpResponse.Status
1017+
return ruleresult.Pass, ""
10241018
}
10251019

10261020
// LibraryPropertiesArchitecturesFieldMissing checks for missing library.properties "architectures" field.

‎internal/rule/rulefunction/packageindex.go

+167
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
package rulefunction
1717

1818
import (
19+
"strings"
20+
1921
"github.com/arduino/arduino-lint/internal/project/packageindex"
2022
"github.com/arduino/arduino-lint/internal/project/projectdata"
2123
"github.com/arduino/arduino-lint/internal/rule/ruleresult"
@@ -83,3 +85,168 @@ func PackageIndexFormat() (result ruleresult.Type, output string) {
8385

8486
return ruleresult.Pass, ""
8587
}
88+
89+
// PackageIndexPackagesWebsiteURLDeadLink checks for dead links in packages[].websiteURL.
90+
func PackageIndexPackagesWebsiteURLDeadLink() (result ruleresult.Type, output string) {
91+
if projectdata.PackageIndexLoadError() != nil {
92+
return ruleresult.NotRun, "Error loading package index"
93+
}
94+
95+
nonCompliantIDs := []string{}
96+
for _, data := range projectdata.PackageIndexPackages() {
97+
url, ok := data.Object["websiteURL"].(string)
98+
if !ok {
99+
continue
100+
}
101+
102+
if url == "" {
103+
continue
104+
}
105+
106+
if checkURL(url) == nil {
107+
continue
108+
}
109+
110+
nonCompliantIDs = append(nonCompliantIDs, data.ID)
111+
}
112+
113+
if len(nonCompliantIDs) > 0 {
114+
return ruleresult.Fail, strings.Join(nonCompliantIDs, ", ")
115+
}
116+
117+
return ruleresult.Pass, ""
118+
}
119+
120+
// PackageIndexPackagesHelpOnlineDeadLink checks for dead links in packages[].help.online.
121+
func PackageIndexPackagesHelpOnlineDeadLink() (result ruleresult.Type, output string) {
122+
if projectdata.PackageIndexLoadError() != nil {
123+
return ruleresult.NotRun, "Error loading package index"
124+
}
125+
126+
nonCompliantIDs := []string{}
127+
for _, data := range projectdata.PackageIndexPackages() {
128+
help, ok := data.Object["help"].(map[string]interface{})
129+
if !ok {
130+
continue
131+
}
132+
133+
url, ok := help["online"].(string)
134+
if !ok {
135+
continue
136+
}
137+
138+
if url == "" {
139+
continue
140+
}
141+
142+
if checkURL(url) == nil {
143+
continue
144+
}
145+
146+
nonCompliantIDs = append(nonCompliantIDs, data.ID)
147+
}
148+
149+
if len(nonCompliantIDs) > 0 {
150+
return ruleresult.Fail, strings.Join(nonCompliantIDs, ", ")
151+
}
152+
153+
return ruleresult.Pass, ""
154+
}
155+
156+
// PackageIndexPackagesPlatformsHelpOnlineDeadLink checks for dead links in packages[].platforms[].help.online.
157+
func PackageIndexPackagesPlatformsHelpOnlineDeadLink() (result ruleresult.Type, output string) {
158+
if projectdata.PackageIndexLoadError() != nil {
159+
return ruleresult.NotRun, "Error loading package index"
160+
}
161+
162+
nonCompliantIDs := []string{}
163+
for _, data := range projectdata.PackageIndexPlatforms() {
164+
help, ok := data.Object["help"].(map[string]interface{})
165+
if !ok {
166+
continue
167+
}
168+
169+
url, ok := help["online"].(string)
170+
if !ok {
171+
continue
172+
}
173+
174+
if url == "" {
175+
continue
176+
}
177+
178+
if checkURL(url) == nil {
179+
continue
180+
}
181+
182+
nonCompliantIDs = append(nonCompliantIDs, data.ID)
183+
}
184+
185+
if len(nonCompliantIDs) > 0 {
186+
return ruleresult.Fail, strings.Join(nonCompliantIDs, ", ")
187+
}
188+
189+
return ruleresult.Pass, ""
190+
}
191+
192+
// PackageIndexPackagesPlatformsURLDeadLink checks for dead links in packages[].platforms[].url.
193+
func PackageIndexPackagesPlatformsURLDeadLink() (result ruleresult.Type, output string) {
194+
if projectdata.PackageIndexLoadError() != nil {
195+
return ruleresult.NotRun, "Error loading package index"
196+
}
197+
198+
nonCompliantIDs := []string{}
199+
for _, data := range projectdata.PackageIndexPlatforms() {
200+
url, ok := data.Object["url"].(string)
201+
if !ok {
202+
continue
203+
}
204+
205+
if url == "" {
206+
continue
207+
}
208+
209+
if checkURL(url) == nil {
210+
continue
211+
}
212+
213+
nonCompliantIDs = append(nonCompliantIDs, data.ID)
214+
}
215+
216+
if len(nonCompliantIDs) > 0 {
217+
return ruleresult.Fail, strings.Join(nonCompliantIDs, ", ")
218+
}
219+
220+
return ruleresult.Pass, ""
221+
}
222+
223+
// PackageIndexPackagesToolsSystemsURLDeadLink checks for dead links in packages[].tools[].systems[].url.
224+
func PackageIndexPackagesToolsSystemsURLDeadLink() (result ruleresult.Type, output string) {
225+
if projectdata.PackageIndexLoadError() != nil {
226+
return ruleresult.NotRun, "Error loading package index"
227+
}
228+
229+
nonCompliantIDs := []string{}
230+
for _, data := range projectdata.PackageIndexSystems() {
231+
url, ok := data.Object["url"].(string)
232+
if !ok {
233+
continue
234+
}
235+
236+
if url == "" {
237+
continue
238+
}
239+
240+
if checkURL(url) == nil {
241+
continue
242+
}
243+
244+
nonCompliantIDs = append(nonCompliantIDs, data.ID)
245+
}
246+
247+
if len(nonCompliantIDs) > 0 {
248+
return ruleresult.Fail, strings.Join(nonCompliantIDs, ", ")
249+
}
250+
251+
return ruleresult.Pass, ""
252+
}

‎internal/rule/rulefunction/packageindex_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,54 @@ func TestPackageIndexFormat(t *testing.T) {
110110

111111
checkPackageIndexRuleFunction(PackageIndexFormat, testTables, t)
112112
}
113+
114+
func TestPackageIndexPackagesWebsiteURLDeadLink(t *testing.T) {
115+
testTables := []packageIndexRuleFunctionTestTable{
116+
{"Invalid JSON", "invalid-JSON", ruleresult.NotRun, ""},
117+
{"Dead URLs", "packages-websiteurl-dead", ruleresult.Fail, "^myboard1, myboard2$"},
118+
{"Invalid URL", "packages-websiteurl-invalid", ruleresult.Fail, "^myboard$"},
119+
{"Valid URL", "valid-package-index", ruleresult.Pass, ""},
120+
}
121+
122+
checkPackageIndexRuleFunction(PackageIndexPackagesWebsiteURLDeadLink, testTables, t)
123+
}
124+
125+
func TestPackageIndexPackagesHelpOnlineDeadLink(t *testing.T) {
126+
testTables := []packageIndexRuleFunctionTestTable{
127+
{"Invalid JSON", "invalid-JSON", ruleresult.NotRun, ""},
128+
{"Dead URLs", "packages-help-online-dead", ruleresult.Fail, "^myboard1, myboard2$"},
129+
{"Valid URL", "valid-package-index", ruleresult.Pass, ""},
130+
}
131+
132+
checkPackageIndexRuleFunction(PackageIndexPackagesHelpOnlineDeadLink, testTables, t)
133+
}
134+
135+
func TestPackageIndexPackagesPlatformsHelpOnlineDeadLink(t *testing.T) {
136+
testTables := []packageIndexRuleFunctionTestTable{
137+
{"Invalid JSON", "invalid-JSON", ruleresult.NotRun, ""},
138+
{"Dead URLs", "packages-platforms-help-online-dead", ruleresult.Fail, "^myboard:avr@1\\.0\\.0, myboard:samd@1\\.0\\.0$"},
139+
{"Valid URL", "valid-package-index", ruleresult.Pass, ""},
140+
}
141+
142+
checkPackageIndexRuleFunction(PackageIndexPackagesPlatformsHelpOnlineDeadLink, testTables, t)
143+
}
144+
145+
func TestPackageIndexPackagesPlatformsURLDeadLink(t *testing.T) {
146+
testTables := []packageIndexRuleFunctionTestTable{
147+
{"Invalid JSON", "invalid-JSON", ruleresult.NotRun, ""},
148+
{"Dead URLs", "packages-platforms-url-dead", ruleresult.Fail, "^myboard:avr@1\\.0\\.0, myboard:samd@1\\.0\\.0$"},
149+
{"Valid URL", "valid-package-index", ruleresult.Pass, ""},
150+
}
151+
152+
checkPackageIndexRuleFunction(PackageIndexPackagesPlatformsURLDeadLink, testTables, t)
153+
}
154+
155+
func TestPackageIndexPackagesToolsSystemsURLDeadLink(t *testing.T) {
156+
testTables := []packageIndexRuleFunctionTestTable{
157+
{"Invalid JSON", "invalid-JSON", ruleresult.NotRun, ""},
158+
{"Dead URLs", "packages-tools-systems-url-dead", ruleresult.Fail, "^myboard:CMSIS@4\\.0\\.0-atmel - arm-linux-gnueabihf, myboard:CMSIS@4\\.0\\.0-atmel - i686-mingw32$"},
159+
{"Valid URL", "valid-package-index", ruleresult.Pass, ""},
160+
}
161+
162+
checkPackageIndexRuleFunction(PackageIndexPackagesToolsSystemsURLDeadLink, testTables, t)
163+
}

‎internal/rule/rulefunction/rulefunction.go

+16
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ package rulefunction
1919
import (
2020
"encoding/json"
2121
"fmt"
22+
"net/http"
2223
"regexp"
2324
"strings"
2425

2526
"github.com/arduino/arduino-lint/internal/project/projectdata"
2627
"github.com/arduino/arduino-lint/internal/project/sketch"
2728
"github.com/arduino/arduino-lint/internal/rule/ruleresult"
2829
"github.com/arduino/go-paths-helper"
30+
"github.com/sirupsen/logrus"
2931
)
3032

3133
// Type is the function signature for the rule functions.
@@ -156,3 +158,17 @@ func isValidJSON(path *paths.Path) bool {
156158
}
157159
return json.Valid(data)
158160
}
161+
162+
func checkURL(url string) error {
163+
logrus.Tracef("Checking URL: %s", url)
164+
response, err := http.Head(url)
165+
if err != nil {
166+
return err
167+
}
168+
169+
if response.StatusCode != http.StatusOK {
170+
return fmt.Errorf("%s", response.Status)
171+
}
172+
173+
return nil
174+
}

0 commit comments

Comments
 (0)
Please sign in to comment.