From 04fdb5d10dc7b3dcfffca075506bbd9a98b598db Mon Sep 17 00:00:00 2001 From: Shunsuke Suzuki Date: Sun, 15 Dec 2024 17:49:48 +0900 Subject: [PATCH] feat: support getting package versions from external files --- .github/workflows/wc-integration-test.yaml | 10 +++ json-schema/aqua-yaml.json | 3 + pkg/config-reader/reader.go | 13 ++++ pkg/config/aqua/config.go | 1 + pkg/expr/version_expr.go | 75 ++++++++++++++++++++++ tests/version_expr_file/.terraform-version | 1 + tests/version_expr_file/aqua.yaml | 18 ++++++ tests/version_expr_json/aqua.yaml | 16 +++++ tests/version_expr_json/version.json | 3 + tests/version_expr_yaml/aqua.yaml | 16 +++++ tests/version_expr_yaml/version.yaml | 1 + 11 files changed, 157 insertions(+) create mode 100644 pkg/expr/version_expr.go create mode 100644 tests/version_expr_file/.terraform-version create mode 100644 tests/version_expr_file/aqua.yaml create mode 100644 tests/version_expr_json/aqua.yaml create mode 100644 tests/version_expr_json/version.json create mode 100644 tests/version_expr_yaml/aqua.yaml create mode 100644 tests/version_expr_yaml/version.yaml diff --git a/.github/workflows/wc-integration-test.yaml b/.github/workflows/wc-integration-test.yaml index 711a725f5..cb097223f 100644 --- a/.github/workflows/wc-integration-test.yaml +++ b/.github/workflows/wc-integration-test.yaml @@ -91,6 +91,16 @@ jobs: run: diff aqua.yaml expect.yaml working-directory: tests/insert + - name: Test version_expr readFile + run: aqua which -v terraform + working-directory: tests/version_expr_file + - name: Test version_expr readJSON + run: aqua which -v terraform + working-directory: tests/version_expr_json + - name: Test version_expr readYAML + run: aqua which -v terraform + working-directory: tests/version_expr_yaml + - run: aqua g -i suzuki-shunsuke/tfcmt working-directory: tests/main - name: add duplicated package diff --git a/json-schema/aqua-yaml.json b/json-schema/aqua-yaml.json index d05142f45..70a0c5c0e 100644 --- a/json-schema/aqua-yaml.json +++ b/json-schema/aqua-yaml.json @@ -97,6 +97,9 @@ "go_version_file": { "type": "string" }, + "version_expr": { + "type": "string" + }, "vars": { "type": "object" }, diff --git a/pkg/config-reader/reader.go b/pkg/config-reader/reader.go index 1871edb1f..1da00351d 100644 --- a/pkg/config-reader/reader.go +++ b/pkg/config-reader/reader.go @@ -10,6 +10,7 @@ import ( "github.com/aquaproj/aqua/v2/pkg/config" "github.com/aquaproj/aqua/v2/pkg/config/aqua" + "github.com/aquaproj/aqua/v2/pkg/expr" "github.com/aquaproj/aqua/v2/pkg/osfile" "github.com/sirupsen/logrus" "github.com/spf13/afero" @@ -97,6 +98,18 @@ func (r *ConfigReader) readPackage(logE *logrus.Entry, configFilePath string, pk } return nil, nil } + if pkg.VersionExpr != "" { + // version_expr + dir := filepath.Dir(configFilePath) + s, err := expr.EvalVersionExpr(r.fs, dir, pkg.VersionExpr) + if err != nil { + return nil, fmt.Errorf("evaluate a version_expr: %w", logerr.WithFields(err, logrus.Fields{ + "version_expr": pkg.VersionExpr, + })) + } + pkg.Version = s + return nil, nil //nolint:nilnil + } if pkg.Import == "" { // version return nil, nil diff --git a/pkg/config/aqua/config.go b/pkg/config/aqua/config.go index a78aa7c83..69c184f74 100644 --- a/pkg/config/aqua/config.go +++ b/pkg/config/aqua/config.go @@ -17,6 +17,7 @@ type Package struct { Update *Update `yaml:",omitempty" json:"update,omitempty"` FilePath string `json:"-" yaml:"-"` GoVersionFile string `json:"go_version_file,omitempty" yaml:"go_version_file,omitempty"` + VersionExpr string `json:"version_expr,omitempty" yaml:"version_expr,omitempty"` Vars map[string]any `json:"vars,omitempty" yaml:",omitempty"` CommandAliases []*CommandAlias `json:"command_aliases,omitempty" yaml:"command_aliases,omitempty"` } diff --git a/pkg/expr/version_expr.go b/pkg/expr/version_expr.go new file mode 100644 index 000000000..cfdcf0920 --- /dev/null +++ b/pkg/expr/version_expr.go @@ -0,0 +1,75 @@ +package expr + +import ( + "encoding/json" + "fmt" + "path/filepath" + "strings" + + "github.com/expr-lang/expr" + "github.com/spf13/afero" + "gopkg.in/yaml.v3" +) + +type Reader struct { + pwd string + fs afero.Fs +} + +func EvalVersionExpr(fs afero.Fs, pwd string, expression string) (string, error) { + r := Reader{fs: fs, pwd: pwd} + compiled, err := expr.Compile(expression, expr.Env(map[string]any{ + "readFile": r.readFile, + "readJSON": r.readJSON, + "readYAML": r.readYAML, + })) + if err != nil { + return "", fmt.Errorf("parse the expression: %w", err) + } + a, err := expr.Run(compiled, map[string]any{ + "readFile": r.readFile, + "readJSON": r.readJSON, + "readYAML": r.readYAML, + }) + if err != nil { + return "", fmt.Errorf("evaluate the expression: %w", err) + } + s, ok := a.(string) + if !ok { + return "", errMustBeBoolean + } + return s, nil +} + +func (r *Reader) read(s string) []byte { + if !filepath.IsAbs(s) { + s = filepath.Join(r.pwd, s) + } + b, err := afero.ReadFile(r.fs, s) + if err != nil { + panic(err) + } + return b +} + +func (r *Reader) readFile(s string) string { + return strings.TrimSpace(string(r.read(s))) +} + +func (r *Reader) readJSON(s string) any { + b := r.read(s) + var a any + if err := json.Unmarshal(b, &a); err != nil { + panic(err) + } + return a +} + +func (r *Reader) readYAML(s string) any { + b := r.read(s) + var a any + if err := yaml.Unmarshal(b, &a); err != nil { + panic(err) + } + return a +} diff --git a/tests/version_expr_file/.terraform-version b/tests/version_expr_file/.terraform-version new file mode 100644 index 000000000..5ad2491cf --- /dev/null +++ b/tests/version_expr_file/.terraform-version @@ -0,0 +1 @@ +1.10.2 diff --git a/tests/version_expr_file/aqua.yaml b/tests/version_expr_file/aqua.yaml new file mode 100644 index 000000000..32826df19 --- /dev/null +++ b/tests/version_expr_file/aqua.yaml @@ -0,0 +1,18 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/main/json-schema/aqua-yaml.json +# aqua - Declarative CLI Version Manager +# https://aquaproj.github.io/ +# checksum: +# enabled: true +# require_checksum: true +# supported_envs: +# - all +registries: +- type: standard + ref: v4.276.0 # renovate: depName=aquaproj/aqua-registry +packages: +- name: hashicorp/terraform + version_expr: | + "v" + readFile('.terraform-version') + # version_template: v{{readFile '.terraform-version'}} + # version_template: v{{(readYAML 'foo.yaml').version}} diff --git a/tests/version_expr_json/aqua.yaml b/tests/version_expr_json/aqua.yaml new file mode 100644 index 000000000..5ca7efbcd --- /dev/null +++ b/tests/version_expr_json/aqua.yaml @@ -0,0 +1,16 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/main/json-schema/aqua-yaml.json +# aqua - Declarative CLI Version Manager +# https://aquaproj.github.io/ +# checksum: +# enabled: true +# require_checksum: true +# supported_envs: +# - all +registries: +- type: standard + ref: v4.276.0 # renovate: depName=aquaproj/aqua-registry +packages: +- name: hashicorp/terraform + version_expr: | + readJSON('version.json').version diff --git a/tests/version_expr_json/version.json b/tests/version_expr_json/version.json new file mode 100644 index 000000000..3f6d4e3ee --- /dev/null +++ b/tests/version_expr_json/version.json @@ -0,0 +1,3 @@ +{ + "version": "1.10.1" +} diff --git a/tests/version_expr_yaml/aqua.yaml b/tests/version_expr_yaml/aqua.yaml new file mode 100644 index 000000000..d195699f5 --- /dev/null +++ b/tests/version_expr_yaml/aqua.yaml @@ -0,0 +1,16 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/main/json-schema/aqua-yaml.json +# aqua - Declarative CLI Version Manager +# https://aquaproj.github.io/ +# checksum: +# enabled: true +# require_checksum: true +# supported_envs: +# - all +registries: +- type: standard + ref: v4.276.0 # renovate: depName=aquaproj/aqua-registry +packages: +- name: hashicorp/terraform + version_expr: | + readYAML('version.yaml').version diff --git a/tests/version_expr_yaml/version.yaml b/tests/version_expr_yaml/version.yaml new file mode 100644 index 000000000..4f6ac6820 --- /dev/null +++ b/tests/version_expr_yaml/version.yaml @@ -0,0 +1 @@ +version: 1.10.1