Skip to content

Commit

Permalink
Add env substitution
Browse files Browse the repository at this point in the history
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
  • Loading branch information
saswatamcode committed Jun 2, 2021
1 parent c46b6e4 commit 7536052
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ This directive runs executable with arguments and put its stderr and stdout outp
"Absolute path links will be converted to relative links to anchor dir as well.").Regexp()
// TODO(bwplotka): Add cache in file?
linksValidateEnabled := cmd.Flag("links.validate", "If true, all links will be validated").Short('l').Bool()
linksValidateConfig := extflag.RegisterPathOrContent(cmd, "links.validate.config", "YAML file for skipping link check, with spec defined in github.com/bwplotka/mdox/pkg/linktransformer.Config", false)
linksValidateConfig := extflag.RegisterPathOrContent(cmd, "links.validate.config", "YAML file for skipping link check, with spec defined in github.com/bwplotka/mdox/pkg/linktransformer.Config", false, true)

cmd.Run(func(ctx context.Context, logger log.Logger) (err error) {
var opts []mdformatter.Option
Expand Down
38 changes: 31 additions & 7 deletions pkg/extflag/pathorcontent.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ package extflag
import (
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"

"github.com/pkg/errors"
"gopkg.in/alecthomas/kingpin.v2"
Expand All @@ -19,7 +22,8 @@ import (
type PathOrContent struct {
flagName string

required bool
envSubstitution bool
required bool

path *string
content *string
Expand All @@ -30,7 +34,7 @@ type FlagClause interface {
}

// RegisterPathOrContent registers PathOrContent flag in kingpinCmdClause.
func RegisterPathOrContent(cmd FlagClause, flagName string, help string, required bool) *PathOrContent {
func RegisterPathOrContent(cmd FlagClause, flagName string, help string, required bool, envSubstitution bool) *PathOrContent {
fileFlagName := fmt.Sprintf("%s-file", flagName)
contentFlagName := flagName

Expand All @@ -41,10 +45,11 @@ func RegisterPathOrContent(cmd FlagClause, flagName string, help string, require
contentFlag := cmd.Flag(contentFlagName, contentHelp).PlaceHolder("<content>").String()

return &PathOrContent{
flagName: flagName,
required: required,
path: fileFlag,
content: contentFlag,
flagName: flagName,
required: required,
path: fileFlag,
content: contentFlag,
envSubstitution: envSubstitution,
}
}

Expand Down Expand Up @@ -74,6 +79,25 @@ func (p *PathOrContent) Content() ([]byte, error) {
if len(content) == 0 && p.required {
return nil, errors.Errorf("flag %s or %s is required for running this command and content cannot be empty.", fileFlagName, p.flagName)
}

if p.envSubstitution {
content = substituteEnvVars(string(content))
}
return content, nil
}

// substituteEnvVars returns content of YAML file with substituted environment variables.
// Will be substituted with empty string if env var isn't set.
// Follows K8s convention, i.e $(...), as mentioned here https://kubernetes.io/docs/tasks/inject-data-application/define-interdependent-environment-variables/.
func substituteEnvVars(content string) []byte {
var replaceWithEnv []string
// Match env variable syntax.
envVarName := regexp.MustCompile(`\$\((?P<var>[a-zA-Z_]+[a-zA-Z0-9_]*)\)`)
loc := envVarName.FindAllStringSubmatchIndex(content, -1)
for i := range loc {
// Add pair to be replaced.
replaceWithEnv = append(replaceWithEnv, content[loc[i][0]:loc[i][1]], os.Getenv(content[loc[i][2]:loc[i][3]]))
}
replacer := strings.NewReplacer(replaceWithEnv...)
contentWithEnv := replacer.Replace(content)
return []byte(contentWithEnv)
}
2 changes: 2 additions & 0 deletions pkg/mdformatter/linktransformer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type Validator struct {
Regex string `yaml:"regex"`
// By default type is `roundtrip`. Could be `github`.
Type ValidatorType `yaml:"type"`
// GitHub repo token to avoid getting rate limited.
Token string `yaml:"token"`
}

type ValidatorType string
Expand Down
6 changes: 2 additions & 4 deletions pkg/mdformatter/linktransformer/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"fmt"
"math"
"net/http"
"os"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -64,7 +63,7 @@ func (v Config) validateGH() error {
v.Validators[i]._maxNum = math.MaxInt64
continue
}
regex, maxNum, err := getGitHubRegex(v.Validators[i].Regex)
regex, maxNum, err := getGitHubRegex(v.Validators[i].Regex, v.Validators[i].Token)
if err != nil {
return err
}
Expand All @@ -75,7 +74,7 @@ func (v Config) validateGH() error {
}

// getGitHubRegex returns GitHub pulls/issues regex from repo name.
func getGitHubRegex(repoRe string) (*regexp.Regexp, int, error) {
func getGitHubRegex(repoRe string, repoToken string) (*regexp.Regexp, int, error) {
// Get reponame from regex.
getRepo := regexp.MustCompile(`(?P<org>[A-Za-z0-9_.-]+)\\\/(?P<repo>[A-Za-z0-9_.-]+)`)
match := getRepo.FindStringSubmatch(repoRe)
Expand All @@ -89,7 +88,6 @@ func getGitHubRegex(repoRe string) (*regexp.Regexp, int, error) {
max := 0
// All GitHub API reqs need to have User-Agent: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#user-agent-required.
client := &http.Client{}
repoToken := os.Getenv("GITHUB_TOKEN")

// Check latest pull request number.
reqPull, err := http.NewRequest("GET", fmt.Sprintf(gitHubAPIURL, reponame, "pulls"), nil)
Expand Down

0 comments on commit 7536052

Please sign in to comment.