Skip to content

Commit

Permalink
Merge pull request #8 from flagship-io/feature/refacto-packages
Browse files Browse the repository at this point in the history
Re-organize packages so that AnalyzeCode function can be called from …
  • Loading branch information
guillaumejacquart authored Sep 22, 2022
2 parents 6ef6ce4 + 2fe4c6a commit 842b1dd
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 129 deletions.
71 changes: 31 additions & 40 deletions internal/files/api/syncFlags.go → internal/api/syncFlags.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@ import (
"bytes"
"encoding/json"
"fmt"
log "github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
"os"

"github.com/flagship-io/code-analyzer/internal/files/model"
log "github.com/sirupsen/logrus"

"github.com/flagship-io/code-analyzer/internal/model"
"github.com/flagship-io/code-analyzer/pkg/config"
)

type SendFlagsParameters struct {
FlagshipAPIURL string
FlagshipAuthAPIURL string
FlagshipClientID string
FlagshipClientSecret string
RepositoryURL string
RepositoryBranch string
}

type AuthRequest struct {
GrantType string `json:"grant_type"`
Scope string `json:"scope"`
Expand Down Expand Up @@ -41,10 +51,10 @@ type Flag struct {
}

// SendFlagsToAPI takes file search result & sends flag info to the API
func SendFlagsToAPI(results []model.FileSearchResult, envId string) (err error) {
func SendFlagsToAPI(cfg *config.Config, results []model.FileSearchResult) (err error) {
flagUsageRequest := FlagUsageRequest{
RepositoryURL: os.Getenv("REPOSITORY_URL"),
RepositoryBranch: os.Getenv("REPOSITORY_BRANCH"),
RepositoryURL: cfg.RepositoryURL,
RepositoryBranch: cfg.RepositoryBranch,
}
var flags []Flag
for _, fr := range results {
Expand All @@ -60,33 +70,18 @@ func SendFlagsToAPI(results []model.FileSearchResult, envId string) (err error)
}
flagUsageRequest.Flags = flags

err = callAPI(envId, flagUsageRequest)
err = callAPI(cfg, flagUsageRequest)

return err
}

func generateAuthenticationToken() error {
if os.Getenv("FLAGSHIP_CLIENT_ID") == "" {
log.WithFields(log.Fields{"variable": "FLAGSHIP_CLIENT_ID"}).Fatal("Missing required environment variable")
}

if os.Getenv("FLAGSHIP_CLIENT_SECRET") == "" {
log.WithFields(log.Fields{"variable": "FLAGSHIP_CLIENT_SECRET"}).Fatal("Missing required environment variable")
}

if os.Getenv("ACCOUNT_ID") == "" {
log.WithFields(log.Fields{"variable": "ACCOUNT_ID"}).Fatal("Missing required environment variable")
}

if os.Getenv("FS_API") == "" {
log.WithFields(log.Fields{"variable": "FS_API"}).Fatal("Missing required environment variable")
}
func generateAuthenticationToken(cfg *config.Config) (string, error) {

authRequest := AuthRequest{
GrantType: "client_credentials",
Scope: "*",
ClientId: os.Getenv("FLAGSHIP_CLIENT_ID"),
ClientSecret: os.Getenv("FLAGSHIP_CLIENT_SECRET"),
ClientId: cfg.FlagshipClientID,
ClientSecret: cfg.FlagshipClientSecret,
}

body, err := json.Marshal(authRequest)
Expand All @@ -95,7 +90,7 @@ func generateAuthenticationToken() error {
log.Fatal("Error while marshal json", err.Error())
}

route := fmt.Sprintf("%s/%s/token?expires_in=0", os.Getenv("FS_AUTH_API"), os.Getenv("ACCOUNT_ID"))
route := fmt.Sprintf("%s/%s/token?expires_in=0", cfg.FlagshipAuthAPIURL, cfg.FlagshipAccountID)

req, err := http.NewRequest("POST", route, bytes.NewBuffer(body))
if err != nil {
Expand All @@ -111,12 +106,12 @@ func generateAuthenticationToken() error {

resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
return "", err
}

if resp.StatusCode == 200 {
if err != nil {
return err
return "", err
}

defer resp.Body.Close()
Expand All @@ -132,28 +127,24 @@ func generateAuthenticationToken() error {
fmt.Println("Can not unmarshal JSON")
}

_ = os.Setenv("FS_AUTH_ACCESS_TOKEN", result.AccessToken)
return result.AccessToken, nil
} else {
body, _ := ioutil.ReadAll(resp.Body)
log.WithFields(log.Fields{
"status": resp.Status,
"body": bytes.NewBuffer(body),
}).Fatal("Error when calling Flagship authentication API")
return "", fmt.Errorf("error when calling Flagship authentication API. Status: %s, body: %s", resp.Status, string(body))
}

return nil
}

func callAPI(envID string, flagInfos FlagUsageRequest) error {
func callAPI(cfg *config.Config, flagInfos FlagUsageRequest) error {

if os.Getenv("FS_AUTH_ACCESS_TOKEN") == "" {
err := generateAuthenticationToken()
if cfg.FlagshipAPIToken == "" {
token, err := generateAuthenticationToken(cfg)
if err != nil {
return err
}
cfg.FlagshipAPIToken = token
}

route := fmt.Sprintf("%s/v1/accounts/%s/account_environments/%s/flags_usage", os.Getenv("FS_API"), os.Getenv("ACCOUNT_ID"), envID)
route := fmt.Sprintf("%s/v1/accounts/%s/account_environments/%s/flags_usage", cfg.FlagshipAPIURL, cfg.FlagshipAccountID, cfg.FlagshipEnvironmentID)

body, _ := json.Marshal(flagInfos)

Expand All @@ -167,7 +158,7 @@ func callAPI(envID string, flagInfos FlagUsageRequest) error {
log.Fatal("Error in request", err.Error())
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("FS_AUTH_ACCESS_TOKEN")))
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", cfg.FlagshipAPIToken))

resp, err := http.DefaultClient.Do(req)

Expand Down
34 changes: 13 additions & 21 deletions internal/files/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"

"github.com/flagship-io/code-analyzer/internal/files/model"
"github.com/flagship-io/code-analyzer/internal/model"
"github.com/flagship-io/code-analyzer/pkg/config"
)

// SearchFiles search code pattern in files and return results and error
func SearchFiles(path string, resultChannel chan model.FileSearchResult) {
func SearchFiles(cfg *config.Config, path string, resultChannel chan model.FileSearchResult) {
// Read file contents
fileContent, err := ioutil.ReadFile(path)
if err != nil {
Expand All @@ -40,7 +39,7 @@ func SearchFiles(path string, resultChannel chan model.FileSearchResult) {
resultChannel <- model.FileSearchResult{
File: path,
Results: nil,
Error: fmt.Errorf("File extension %s not handled", ext),
Error: fmt.Errorf("file extension %s not handled", ext),
}
return
}
Expand Down Expand Up @@ -83,8 +82,8 @@ func SearchFiles(path string, resultChannel chan model.FileSearchResult) {

for _, flagKeyIndex := range flagKeyIndexes {
// Extract the code with a certain number of lines
firstLineIndex := getSurroundingLineIndex(fileContentStr, flagKeyIndex[0], true)
lastLineIndex := getSurroundingLineIndex(fileContentStr, flagKeyIndex[1], false)
firstLineIndex := getSurroundingLineIndex(fileContentStr, flagKeyIndex[0], true, cfg.NbLineCodeEdges)
lastLineIndex := getSurroundingLineIndex(fileContentStr, flagKeyIndex[1], false, cfg.NbLineCodeEdges)
code := fileContentStr[firstLineIndex:lastLineIndex]
value := fileContentStr[flagKeyIndex[0]:flagKeyIndex[1]]
// Better value wrapper for code highlighting (5 chars wrapping)
Expand All @@ -100,7 +99,7 @@ func SearchFiles(path string, resultChannel chan model.FileSearchResult) {
FlagKey: value,
CodeLines: code,
CodeLineHighlight: codeLineHighlight,
CodeLineURL: getCodeURL(path, &lineNumber),
CodeLineURL: getCodeURL(cfg, path, &lineNumber),
// Get line number of the code
LineNumber: lineNumber,
})
Expand All @@ -109,31 +108,24 @@ func SearchFiles(path string, resultChannel chan model.FileSearchResult) {

resultChannel <- model.FileSearchResult{
File: path,
FileURL: getCodeURL(path, nil),
FileURL: getCodeURL(cfg, path, nil),
Results: results,
Error: err,
}
}

func getCodeURL(filePath string, line *int) string {
repositoryURL := os.Getenv("REPOSITORY_URL")
repositoryBranch := os.Getenv("REPOSITORY_BRANCH")

repositorySep := ""
if repositoryURL[len(repositoryURL)-1:] != "/" {
repositorySep = "/"
}
func getCodeURL(cfg *config.Config, filePath string, line *int) string {
repositoryURL := strings.TrimSuffix(cfg.RepositoryURL, "/")
lineAnchor := ""
if line != nil {
lineAnchor = fmt.Sprintf("#L%d", *line)
}
return fmt.Sprintf("%s%s-/blob/%s/%s%s", repositoryURL, repositorySep, repositoryBranch, filePath, lineAnchor)
return fmt.Sprintf("%s/-/blob/%s/%s%s", repositoryURL, cfg.RepositoryBranch, filePath, lineAnchor)
}

func getSurroundingLineIndex(input string, indexPosition int, topDirection bool) int {
func getSurroundingLineIndex(input string, indexPosition int, topDirection bool, nbLineCodeEdges int) int {
i := indexPosition
n := 0
e, _ := strconv.Atoi(os.Getenv("NB_CODE_LINES_EDGES"))
for {
// to top or bottom
if topDirection {
Expand All @@ -152,7 +144,7 @@ func getSurroundingLineIndex(input string, indexPosition int, topDirection bool)

// if new line, in the top direction we don't wan't the first \n in the code
if input[i] == '\n' {
if n == e {
if n == nbLineCodeEdges {
if topDirection {
return i + 1
}
Expand Down
29 changes: 15 additions & 14 deletions internal/files/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ package files

import (
"fmt"
"github.com/flagship-io/code-analyzer/internal/files/model"
"github.com/stretchr/testify/assert"
"os"
"testing"

"github.com/flagship-io/code-analyzer/internal/model"
"github.com/flagship-io/code-analyzer/pkg/config"
"github.com/stretchr/testify/assert"
)

func init() {
_ = os.Setenv("REPOSITORY_URL", "wwww.toto.com")
_ = os.Setenv("REPOSITORY_BRANCH", "master")
_ = os.Setenv("NB_CODE_LINES_EDGES", "5")
var testCfg = &config.Config{
RepositoryURL: "wwww.toto.com",
RepositoryBranch: "master",
NbLineCodeEdges: 5,
}

func TestSearchFiles(t *testing.T) {
Expand Down Expand Up @@ -180,7 +181,7 @@ func TestSearchFiles(t *testing.T) {
var r model.FileSearchResult

for _, c := range cases {
go SearchFiles(c.filePath, resultChannel)
go SearchFiles(testCfg, c.filePath, resultChannel)
r = <-resultChannel
assert.Equal(t, len(c.flags), len(r.Results), fmt.Sprintf("File : %s", c.filePath))
for i, result := range r.Results {
Expand All @@ -190,8 +191,8 @@ func TestSearchFiles(t *testing.T) {
assert.Equal(t,
fmt.Sprintf(
"%s/-/blob/%s/%s#L%d",
os.Getenv("REPOSITORY_URL"),
os.Getenv("REPOSITORY_BRANCH"),
testCfg.RepositoryURL,
testCfg.RepositoryBranch,
c.filePath,
c.flags[i].lineNumber,
),
Expand Down Expand Up @@ -229,8 +230,8 @@ func TestGetSurroundingLineIndex(t *testing.T) {
11;
12;
13;`
start := getSurroundingLineIndex(code, 24, true)
end := getSurroundingLineIndex(code, 24, false)
start := getSurroundingLineIndex(code, 24, true, testCfg.NbLineCodeEdges)
end := getSurroundingLineIndex(code, 24, false, testCfg.NbLineCodeEdges)

assert.Equal(t, 7, start)
assert.Equal(t, 48, end)
Expand All @@ -243,8 +244,8 @@ func TestGetSurroundingLineIndexEdgeCases(t *testing.T) {
3;
4;
5;`
start := getSurroundingLineIndex(code, 8, true)
end := getSurroundingLineIndex(code, 8, false)
start := getSurroundingLineIndex(code, 8, true, testCfg.NbLineCodeEdges)
end := getSurroundingLineIndex(code, 8, false, testCfg.NbLineCodeEdges)

assert.Equal(t, 0, start)
assert.Equal(t, 17, end)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
64 changes: 60 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
package main

import (
"os"
"strconv"
"strings"

"github.com/flagship-io/code-analyzer/pkg/config"
"github.com/flagship-io/code-analyzer/pkg/handler"
"github.com/joho/godotenv"
log "github.com/sirupsen/logrus"
"os"
)

func extractConfig() *config.Config {
cfg := &config.Config{
FlagshipAPIURL: "https://api.flagship.io",
FlagshipAuthAPIURL: "https://auth.flagship.io",
FlagshipClientID: os.Getenv("FLAGSHIP_CLIENT_ID"),
FlagshipClientSecret: os.Getenv("FLAGSHIP_CLIENT_SECRET"),
FlagshipAPIToken: os.Getenv("FS_AUTH_ACCESS_TOKEN"),
FlagshipAccountID: os.Getenv("ACCOUNT_ID"),
FlagshipEnvironmentID: os.Getenv("ENVIRONMENT_ID"),
Directory: ".",
RepositoryURL: os.Getenv("REPOSITORY_URL"),
RepositoryBranch: "master",
FilesToExcludes: []string{".git"},
NbLineCodeEdges: 1,
SearchCustomRegex: os.Getenv("CUSTOM_REGEX_JSON"),
}

if os.Getenv("FS_API") != "" {
cfg.FlagshipAPIURL = os.Getenv("FS_API")
}

if os.Getenv("FS_AUTH_API") != "" {
cfg.FlagshipAuthAPIURL = os.Getenv("FS_AUTH_API")
}

if os.Getenv("REPOSITORY_BRANCH") != "" {
cfg.RepositoryBranch = os.Getenv("REPOSITORY_BRANCH")
}

if os.Getenv("FILES_TO_EXCLUDE") != "" {
cfg.FilesToExcludes = strings.Split(os.Getenv("FILES_TO_EXCLUDE"), ",")
}

if os.Getenv("DIRECTORY") != "" {
cfg.Directory = os.Getenv("DIRECTORY")
}

if os.Getenv("NB_CODE_LINES_EDGES") != "" {
cfg.NbLineCodeEdges, _ = strconv.Atoi(os.Getenv("NB_CODE_LINES_EDGES"))
}

return cfg
}

func main() {
log.SetFormatter(&log.TextFormatter{
FullTimestamp: true,
Expand All @@ -18,11 +66,19 @@ func main() {
log.Info("Fail to load .env file")
}

if os.Getenv("ENABLE_LOGS") == "1" {
log.SetLevel(log.InfoLevel)
levelString := os.Getenv("LOG_LEVEL")
if levelString != "" {
lvl, err := log.ParseLevel(levelString)
if err != nil {
log.Fatalf("log level %s is invalid", levelString)
}
log.SetLevel(lvl)
}

err := handler.AnalyzeCode()
cfg := extractConfig()
cfg.Validate()

err := handler.AnalyzeCode(cfg)
if err != nil {
log.Fatalf("Analyser failed with error: %v", err)
}
Expand Down
Loading

0 comments on commit 842b1dd

Please sign in to comment.