Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reusing configuration #56

Open
ianlewis opened this issue Jun 8, 2023 · 11 comments
Open

Reusing configuration #56

ianlewis opened this issue Jun 8, 2023 · 11 comments
Labels
enhancement New feature or request
Milestone

Comments

@ianlewis
Copy link

ianlewis commented Jun 8, 2023

Is there a way to reuse configuration from one rule in another? For example, I'd like to create a common rule for all code, and then sub-rules for test and non-test code. As it stands currently, I think I need to largely duplicate the rule for test and non-test code.

rules:
  main:
    files:
      - $all
      - "!$test"
    allow:
      # allowed packages
    deny:
      # denied packages
  test:
    files:
      - $test
    allow:
      # Copy every everything from main here.
      "github.com/google/go-cmp"
    deny:
      # 

Also, if I need exceptions for a particular package I can't just specify the exception, I have to exclude the package files from the test and non-test rules, copy both the test and non-test rules and then update them with the exception. This becomes pretty hard to maintain pretty quickly.

For example, all of the following rules would be mostly the same except for some small differences.

rules:
  exception:
    # rules for exception
  exception-tests:
    # rules for tests for the exceptional package
  main:
     # rules for everything else
  test:
     # rules for tests for everything else
@dixonwille
Copy link
Member

dixonwille commented Jun 8, 2023

Don't see the need to copy configs. A file can match multiple rules
https://github.com/OpenPeeDeeP/depguard/blob/6a315f2326b2084d60c0a056bcafa10d1e9f5bd7/settings_test.go#LL602C1-L606C4

rules:
  global:
    files:
      - $all
    allow:
      # allowed packages
    deny:
      # denied packages
  test:
    files:
      - $test
    allow:
      "github.com/google/go-cmp"
    deny:
      # 

Removing the "!$test" will from main (I renamed main to global above) will allow all test files to match on both lists and should lint appropriately.

@ianlewis
Copy link
Author

ianlewis commented Jun 8, 2023

Hmm, I don't see it doing that. When I used a configuration like this all of my test files failed with errors saying that I wasn't allowed to import stdlib packages. So it seemed like all rules were run completely independently of each other (I'm using golangci-lint 1.53.2).

I may have been doing something wrong but I'll try to add a simple example when my hands free up.

@dixonwille
Copy link
Member

I do see the flaw in the code. It does match multiple list, but each list is checked independently of each other, so file has to pass all rule sets they are in... I'll see if I can plan something up, will probably use the $variables I introduced in this version as that is the best backwards compatible way to do it. Brute force would be to combine the lists but I believe that is backwards breaking behavior...

@dixonwille
Copy link
Member

https://github.com/OpenPeeDeeP/depguard/blob/6a315f2326b2084d60c0a056bcafa10d1e9f5bd7/depguard.go#LL72C3-L88C4

Relevant code to above comment... Notice that it checks if it is allowed in each list, and if it fails throws a lint error.

@ianlewis
Copy link
Author

ianlewis commented Jun 8, 2023

Apologies. I must have just done something very wrong. I was able to get it to work the way you described and I now can't recreate the config that was failing for me.

I think that what i was trying to do initially was to create a blanket deny in global but then allow it in test when what I should have done is leave it out of the global allow list and only add it to test. Another reason for my confusion is that there is a global allow rule for github.com/google org in my case.

@ianlewis
Copy link
Author

ianlewis commented Jun 8, 2023

Ok, If I have something like the following all the files under exception/ fail badly for me.

rules:                                                                                                                                                                                                                                                                                                                                                                     
  global:                                                                                                                                                                                                                                                                                                                                                                     
    files:                                                                                                                                                                                                                                                                                                                                                                 
      - $all                                                                                                                                                                                                                                                                                                                                                               
    allow:                                                                                                                                                                                                                                                                                                                                                                 
      - $gostd                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                           
  exception:                                                                                                                                                                                                                                                                                                                                                               
    files:                                                                                                                                                                                                                                                                                                                                                                 
      - "**/exception/**/*.go"                                                                                                                                                                                                                                                                                                                                               
    allow:                                                                                                                                                                                                                                                                                                                                                                 
      - "github.com/google/go-cmp"

So it seems that if the allow was empty in exception it will allow anything and so it effectively merges well with global.allow but when I specify a exception.allow then only that list is strictly allowed.

i.e. I can do this.

rules:                                                                                                                                                                                                                                                                                                                                                                     
  all:                                                                                                                                                                                                                                                                                                                                                                     
    files:                                                                                                                                                                                                                                                                                                                                                                 
      - $all                                                                                                                                                                                                                                                                                                                                                               
    allow:                                                                                                                                                                                                                                                                                                                                                                 
      - $gostd                                                                                                                                                                                                                                                                                                                                                             
      - "github.com/google/go-cmp"                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                           
  main:                                                                                                                                                                                                                                                                                                                                                                    
    files:                                                                                                                                                                                                                                                                                                                                                                 
      - $all                                                                                                                                                                                                                                                                                                                                                               
      - "!**/exception/**/*.go"                                                                                                                                                                                                                                                                                                                                              
    deny:                                                                                                                                                                                                                                                                                                                                                                  
      - pkg: "github.com/google/go-cmp"                                                                                                                                                                                                                                                                                                                                    
        desc: Please don't use go-cmp

So If I want to have a global allow list and grant exceptions for individual directories it seems the best way to do that currently is to allow everything in the global rule and deny it in the main rule. This is kind of the reverse of how I wanted to express the exception.

@ianlewis
Copy link
Author

ianlewis commented Jun 8, 2023

@advdv
Copy link

advdv commented Jun 9, 2023

I'm kinda running into the same issue. I think this linter has great potential but I just couldn't get the lists to "overlap" to prevent having to specify dependencies twice. I personally think the README needs a big section that explains the "mental model" a bit better. Maybe more examples, or maybe just different approaches to whitelisting/blacklisting in certain ways. Like, what happens if a package is in two lists? what if it is allowed in one and denied in the other? Is the order of rules important? etc.

If it helps, I'm trying it on this repo: https://github.com/crewlinker/clgo with a end configuration like this:

  depguard:
    rules:
      tasks:
        files:
          - "**/magefiles/*.go"
        allow:
          - $gostd
          - github.com/magefile/mage
      main:
        files:
          - $all
          - "!$test"
          - "!**/magefiles/*.go"
          - "!**/clzap/logs_testutil.go" #special exception for ginkgo writer
        allow:
          - $gostd
          - github.com/aws/aws-lambda-go/lambda
          - github.com/crewlinker/clgo/
          - github.com/caarlos0/env/v6
          - github.com/aws/aws-sdk-go-v2
          - github.com/go-logr/zapr
          - github.com/jackc/pgx/v5
          - github.com/redis/go-redis
          - github.com/XSAM/otelsql
          - ariga.io/atlas/sql
      zaplog:
        files:
          - "**/clzap/logs_testutil.go"
        allow:
          - $gostd
          - github.com/onsi/ginkgo/v2
      tests:
        files:
          - $test
        allow: 
          - $gostd
          - github.com/crewlinker/clgo/
          - github.com/onsi/ginkgo/v2
          - github.com/joho/godotenv
          - github.com/caarlos0/env/v6
          - github.com/aws/aws-sdk-go-v2
          - github.com/go-logr/zapr
          - github.com/jackc/pgx/v5
          - github.com/redis/go-redis
          - github.com/XSAM/otelsql
          - ariga.io/atlas/sql
          - github.com/onsi/gomega

I would expect that if I remove !$test from the "main" rule it would starting to overlap and I wouldn't have to provide the same dependencies in the "tests" rule but it didn't work for me.

NOTE2: In the same repo above I didn't need to specify go.uber.org/fx or go.uber.org/zap at all, which confused me as well. I feel like I'm just not getting it.

@ianlewis
Copy link
Author

Yeah, IIUC, you'd need to do something like the following if you want to dedup the allow list. Which is a bit ununintuitive to express.

depguard:
  rules:
    global:
      files:
        - $all
        - "!**/magefiles/*.go"
        - "!**/clzap/logs_testutil.go"
      allow:
        - $gostd
        - github.com/aws/aws-sdk-go-v2
        - github.com/crewlinker/clgo/
        - github.com/caarlos0/env/v6
        - github.com/go-logr/zapr
        - github.com/jackc/pgx/v5
        - github.com/redis/go-redis
        - github.com/XSAM/otelsql
        - ariga.io/atlas/sql

        # Allowed in non-test code
        - github.com/aws/aws-lambda-go/lambda

        # Allowed in test code.
        - github.com/onsi/ginkgo/v2
        - github.com/joho/godotenv
        - github.com/onsi/gomega

    tasks:
      files:
        - "**/magefiles/*.go"
      allow:
        - $gostd
        - github.com/magefile/mage

    zaplog:
      files:
        - "**/clzap/logs_testutil.go"
      allow:
        - $gostd
        - github.com/onsi/ginkgo/v2

    main:
      files:
        - $all
        - "!$test"
        - "!**/magefiles/*.go" # special exception for magefiles
        - "!**/clzap/logs_testutil.go" # special exception for ginkgo writer
      deny:
        - pkg: github.com/onsi/ginkgo/v2
          description: Don't use.
        - pkg: github.com/joho/godotenv
          description: Don't use.
        - pkg: github.com/onsi/gomega
          description: Don't use.

    tests:
      files:
        - $test
      deny:
        - pkg: github.com/aws/aws-lambda-go/lambda
          description: Don't use.

@dixonwille
Copy link
Member

I have not forgotten about this, just have not had the time to look for, much less develop, a backwards compatible solution.

Fixing the loop I linked earlier is a breaking change as configurations that were setup to use it, were expecting that behavior... The loop assumes it needs to pass all lists a file matches for (which is most strict AND logic) but appears some want a less strict OR logic. Maybe add a configuration that defaults to the AND logic but can be configure to OR logic...

It seems 2 options are backwards compatible.

  1. Add variables that allow you to reference another list's allow/deny lists
  2. Create a configuration field that defaults to the "STRICT" mode but can be configured to a "LAX" mode (naming should be revised).

Open to other solutions or some pro/con conversation on either solution? In theory we could introduce both options.

@dixonwille dixonwille added enhancement New feature or request help wanted Extra attention is needed go Pull requests that update Go code labels Jul 6, 2023
@dixonwille
Copy link
Member

So I have Strict and Lax mode for the package matching setup. But I would like to add reference variables as well to cover this issue more thoroughly.

@dixonwille dixonwille added this to the v2.2.0 milestone Oct 31, 2023
@dixonwille dixonwille removed help wanted Extra attention is needed go Pull requests that update Go code labels Oct 31, 2023
@dixonwille dixonwille modified the milestones: v2.2.0, v2.3.0 Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants