Skip to content

Commit

Permalink
Merge pull request #89 from DepsHubHQ/add-github-action
Browse files Browse the repository at this point in the history
Add a DepsHub github action
  • Loading branch information
semanser authored Jan 16, 2025
2 parents 8e80b4b + 8dcea93 commit 76eec96
Show file tree
Hide file tree
Showing 12 changed files with 851 additions and 1,072 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/depshub.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: DepsHub
on:
- pull_request
- push
- workflow_dispatch

jobs:
depshub:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DepsHubHQ/github-action@v1
7 changes: 6 additions & 1 deletion cmd/depshub/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var lintCmd = &cobra.Command{
for _, mistake := range mistakes {
if mistake.Rule.GetLevel() == types.LevelError {
errorsCount++
} else {
} else if mistake.Rule.GetLevel() == types.LevelWarning {
warningsCount++
}
}
Expand Down Expand Up @@ -117,6 +117,11 @@ var lintCmd = &cobra.Command{
}
}

style := lipgloss.NewStyle().Foreground(lipgloss.Color("2"))
if errorsCount == 0 && warningsCount == 0 {
fmt.Println(style.Render("No issues found"))
}

if errorsCount > 0 {
os.Exit(1)
}
Expand Down
18 changes: 18 additions & 0 deletions depshub.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,21 @@ manifest_files:
rules:
- name: "allowed-licenses"
value: ["", "MIT", "Apache-2.0", "BSD-3-Clause"]
- filter: "**/docs/package.json"
packages: ["@astrojs/check", "@astrojs/starlight", "sharp"]
rules:
- name: "no-unstable"
disabled: true
- filter: "**/docs/package.json"
packages: ["@radix-ui/colors"]
rules:
- name: "max-package-age"
disabled: true
- filter: "**/go.mod"
packages:
- "github.com/edoardottt/depsdev"
- "github.com/sabhiram/go-gitignore"
- "golang.org/x/mod"
rules:
- name: "no-unstable"
disabled: true
8 changes: 4 additions & 4 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
},
"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/starlight": "0.30.5",
"@astrojs/starlight": "0.31.0",
"@radix-ui/colors": "^3.0.0",
"astro": "5.0.9",
"sharp": "^0.32.5",
"typescript": "^5.7.2"
"astro": "5.1.7",
"sharp": "^0.33.5",
"typescript": "^5.7.3"
},
"devDependencies": {
"prettier": "3.4.2"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Set the maximum allowed package age for the manifest file in months.

| Type | Default Value |
| --------------- | ------------- |
| Number (Months) | `36` |
| Number (Months) | `12` |

### max-patch-updates

Expand Down
1,820 changes: 767 additions & 1,053 deletions docs/yarn.lock

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions internal/linter/linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ func (l Linter) Run(path string, configPath string) (mistakes []types.Mistake, e
return nil, fmt.Errorf("failed to scan manifests: %w", err)
}

fmt.Printf("Scanning %d manifest files. \n", len(manifests))

for _, manifest := range manifests {
fmt.Printf(" - %s \n", manifest.Path)
}

uniqueDependencies := scanner.UniqueDependencies(manifests)

packagesData, err := sources.NewFetcher().Fetch(uniqueDependencies)
Expand Down
16 changes: 15 additions & 1 deletion internal/linter/rules/max_libyear.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func (r RuleMaxLibyear) Check(manifests []types.Manifest, info types.PackagesInf
mistakes := []types.Mistake{}

totalLibyear := 0.0
topPackageContributors := make(map[string]float64)

for _, manifest := range manifests {
if !r.IsSupported(manifest.Manager) {
Expand All @@ -77,19 +78,32 @@ func (r RuleMaxLibyear) Check(manifests []types.Manifest, info types.PackagesInf

if pkg, ok := info[dep.Name]; ok {
if t, ok := pkg.Time[dep.Version]; ok {
if t.IsZero() {
continue
}

diff := time.Since(t)
diffHours := diff.Abs().Hours()
totalLibyear += diffHours / (365 * 24)

topPackageContributors[dep.Name] += diffHours / (365 * 24)
}
}
}
}

if totalLibyear > r.value {
message := fmt.Sprintf("The total libyear of all dependencies is too high.\n Allowed libyear: %.2f. Total libyear: %.2f", r.value, totalLibyear)

message += "\n\nTop outdated packages:"
for pkg, libyear := range topPackageContributors {
message += fmt.Sprintf("\n%s: %.2f", pkg, libyear)
}

mistakes = append(mistakes, types.Mistake{
Rule: r,
Definitions: []types.Definition{{
Path: fmt.Sprintf("Allowed libyear: %.2f. Total libyear: %.2f", r.value, totalLibyear),
Path: message,
}},
})
}
Expand Down
4 changes: 0 additions & 4 deletions internal/linter/rules/max_libyear_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package rules

import (
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -199,10 +198,7 @@ func TestRuleMaxLibyear(t *testing.T) {
assert.Contains(t, path, "Total libyear:")

// Parse the total libyear value to verify it's in the expected range
var allowedLibyear, totalLibyear float64
_, err := fmt.Sscanf(path, "Allowed libyear: %f. Total libyear: %f", &allowedLibyear, &totalLibyear)
assert.NoError(t, err)
assert.Greater(t, totalLibyear, DefaultMaxLibyear)
} else {
assert.Equal(t, tt.want, got)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/linter/rules/max_package_age.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/depshubhq/depshub/pkg/types"
)

const DefaultMaxPackageAge = 36
const DefaultMaxPackageAge = 12

type RuleMaxPackageAge struct {
name string
Expand Down Expand Up @@ -75,7 +75,7 @@ func (r RuleMaxPackageAge) Check(manifests []types.Manifest, info types.Packages
}

for version, t := range pkg.Time {
if version == dep.Version && t.Before(time.Now().AddDate(0, -r.value, 0)) {
if version == dep.Version && !t.IsZero() && t.Before(time.Now().AddDate(0, -r.value, 0)) {
mistakes = append(mistakes, types.Mistake{
Rule: r,
Definitions: []types.Definition{
Expand Down
4 changes: 2 additions & 2 deletions internal/linter/rules/max_package_age_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ func TestRuleMaxPackageAge(t *testing.T) {
info: types.PackagesInfo{
"old-pkg": {
Time: map[string]time.Time{
"1.0.0": now.AddDate(0, -(DefaultMaxPackageAge + 12), 0), // 12 months older than max age
"1.0.0": now.AddDate(0, -(DefaultMaxPackageAge + 1), 0), // 1 months older than max age
},
},
"new-pkg": {
Time: map[string]time.Time{
"1.0.0": now.AddDate(0, -12, 0), // Only 12 months old
"1.0.0": now.AddDate(0, -(DefaultMaxPackageAge - 1), 0), // 1 month newer than max age
},
},
},
Expand Down
22 changes: 18 additions & 4 deletions pkg/manager/npm/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,28 @@ func (Npm) Dependencies(path string) ([]types.Dependency, error) {
return dependencies, nil
}

// LockfilePath checks for the existence of npm and yarn lockfiles and returns the path of the found lockfile.
func (Npm) LockfilePath(path string) (string, error) {
lockfilePath := filepath.Join(filepath.Dir(path), "package-lock.json")
npmLockfilePath := filepath.Join(filepath.Dir(path), "package-lock.json")
yarnLockfilePath := filepath.Join(filepath.Dir(path), "yarn.lock")

// Check for npm lockfile
if _, err := os.Stat(npmLockfilePath); err == nil {
return npmLockfilePath, nil // Return npm lockfile path if it exists
} else if !os.IsNotExist(err) {
return "", fmt.Errorf("error checking npm lockfile: %v", err)
}

if _, err := os.Stat(lockfilePath); os.IsNotExist(err) {
return "", fmt.Errorf("lockfile not found")
// TODO This is a temporary fix to support yarn lockfiles
// Check for yarn lockfile
if _, err := os.Stat(yarnLockfilePath); err == nil {
return yarnLockfilePath, nil // Return yarn lockfile path if it exists
} else if !os.IsNotExist(err) {
return "", fmt.Errorf("error checking yarn lockfile: %v", err)
}

return lockfilePath, nil
// If neither lockfile exists
return "", fmt.Errorf("no lockfile found (neither %s nor %s)", npmLockfilePath, yarnLockfilePath)
}

// Returns the version without any prefix or suffix
Expand Down

0 comments on commit 76eec96

Please sign in to comment.