11package data
22
3- import (
4- "context"
5- "fmt"
6- "path/filepath"
7-
8- "github.com/privateerproj/privateer-sdk/config"
9- "github.com/shurcooL/githubv4"
10- )
11-
123// GraphqlRepoData is used in a query to get general repository information
134type GraphqlRepoData struct {
145 Repository struct {
@@ -85,22 +76,8 @@ type GraphqlRepoData struct {
8576 Description string
8677 }
8778 ContributingGuidelines struct {
88- Body string
89- ResourcePath string
79+ Body string
9080 }
91- DependencyGraphManifests struct {
92- TotalCount int
93- Nodes []struct {
94- Filename string
95- Dependencies struct {
96- TotalCount int
97- Nodes []struct {
98- PackageName string
99- Requirements string
100- }
101- } `graphql:"dependencies(first: 100)"`
102- } `graphql:"nodes"`
103- } `graphql:"dependencyGraphManifests(first: 100)"`
10481 Releases struct {
10582 Nodes []struct {
10683 TagName string
@@ -115,113 +92,3 @@ type GraphqlRepoData struct {
11592 } `graphql:"releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC})"`
11693 } `graphql:"repository(owner: $owner, name: $name)"`
11794}
118-
119- // GraphqlRepoTree is used in a query to get top 3 levels of the repository contents
120- type GraphqlRepoTree struct {
121- Repository struct {
122- Object struct {
123- Tree struct {
124- Entries []struct {
125- Name string
126- Type string // "blob" for files, "tree" for directories
127- Path string
128- Object * struct {
129- Tree struct {
130- Entries []struct {
131- Name string
132- Type string
133- Path string
134- Object * struct {
135- Tree struct {
136- Entries []struct {
137- Name string
138- Type string
139- Path string
140- }
141- } `graphql:"... on Tree"`
142- } `graphql:"object"`
143- }
144- } `graphql:"... on Tree"`
145- } `graphql:"object"`
146- }
147- } `graphql:"... on Tree"`
148- } `graphql:"object(expression: $branch)"`
149- } `graphql:"repository(owner: $owner, name: $name)"`
150- }
151-
152- func checkTreeForBinaries (tree * GraphqlRepoTree , binariesFound []string ) []string {
153- for _ , entry := range tree .Repository .Object .Tree .Entries {
154- binariesFound = identifyBinaries (binariesFound , entry .Type , entry .Name )
155- if entry .Type == "tree" {
156- for _ , subEntry := range entry .Object .Tree .Entries {
157- binariesFound = identifyBinaries (binariesFound , subEntry .Type , subEntry .Name )
158- if subEntry .Type == "tree" {
159- for _ , subSubEntry := range subEntry .Object .Tree .Entries {
160- binariesFound = identifyBinaries (binariesFound , subSubEntry .Type , subSubEntry .Name )
161- // if subSubEntry.Type == "tree" {
162- // TODO: The current GraphQL call stops after 3 levels of depth.
163- // Additional API calls will be required for recursion if another tree is found.
164- // }
165- }
166- }
167- }
168- }
169- }
170- return binariesFound
171- }
172-
173- func identifyBinaries (binariesFound []string , filetype string , filename string ) []string {
174- if filetype == "blob" {
175- if isBinaryFile (filename ) {
176- binariesFound = append (binariesFound , filename )
177- }
178- }
179- return binariesFound
180- }
181-
182- // TODO: this is a lightweight check, looking at filenames only.
183- // GitHub's GraphQL API has an 'isBinary' field that could be used for a more accurate check,
184- // but I didn't manage to get that query working as expected.
185- func isBinaryFile (filename string ) bool {
186- binaryExtensions := map [string ]bool {
187- "" : true , ".exe" : true , ".dll" : true , ".so" : true , ".pdf" : true ,
188- ".zip" : true , ".tar" : true , ".mp4" : true , ".mp3" : true ,
189- }
190- knownFilenames := map [string ]bool {
191- // Extend this with more known filenames as needed
192- "README" : true , "LICENSE" : true , "CHANGELOG" : true , "CONTRIBUTING" : true ,
193- "CODE_OF_CONDUCT" : true , "TODO" : true , "SECURITY" : true , "NOTICE" : true , "CODEOWNERS" : true ,
194- ".gitignore" : true , ".gitattributes" : true , "Makefile" : true , "Dockerfile" : true ,
195- "Vagrantfile" : true , "Gemfile" : true , "Procfile" : true , "Brewfile" : true , "MANIFEST" : true ,
196- }
197- if knownFilenames [filename ] {
198- return false
199- }
200- ext := filepath .Ext (filename )
201- return binaryExtensions [ext ]
202- }
203-
204- func fetchGraphqlRepoTree (config * config.Config , client * githubv4.Client , branch string ) (tree * GraphqlRepoTree , err error ) {
205- path := "" // TODO: I suspected we should be able to target subdirectories this way, but it hasn't succeeded
206-
207- fullPath := fmt .Sprintf ("%s:%s" , branch , path ) // Ensure correct format
208-
209- variables := map [string ]interface {}{
210- "owner" : githubv4 .String (config .GetString ("owner" )),
211- "name" : githubv4 .String (config .GetString ("repo" )),
212- "branch" : githubv4 .String (fullPath ),
213- }
214-
215- err = client .Query (context .Background (), & tree , variables )
216-
217- return tree , err
218- }
219-
220- func getSuspectedBinaries (client * githubv4.Client , config * config.Config , branchName string ) (suspectedBinaries []string , err error ) {
221- tree , err := fetchGraphqlRepoTree (config , client , branchName )
222- if err != nil {
223- return nil , err
224- }
225- binaryFileNames := checkTreeForBinaries (tree , []string {})
226- return binaryFileNames , nil
227- }
0 commit comments