Compare commits

..

No commits in common. "v3" and "v3.8.0" have entirely different histories.
v3 ... v3.8.0

10 changed files with 142 additions and 298 deletions

View File

@ -1,20 +0,0 @@
name: "autoapprove"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
autoapprove:
runs-on: ubuntu-latest
steps:
- name: approve
uses: hmarr/auto-approve-action@v3
if: github.actor == 'vtolstov' || github.actor == 'dependabot[bot]'
id: approve
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,21 +0,0 @@
name: "automerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
automerge:
runs-on: ubuntu-latest
if: github.actor == 'vtolstov'
steps:
- name: merge
id: merge
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

View File

@ -3,20 +3,19 @@ on:
push:
branches:
- master
- v3
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.16
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v2
- name: cache
uses: actions/cache@v3
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
@ -32,9 +31,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v2
- name: lint
uses: golangci/golangci-lint-action@v3.4.0
uses: golangci/golangci-lint-action@v2
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.

View File

@ -9,7 +9,7 @@
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "codeql"
name: "CodeQL"
on:
workflow_run:
@ -17,16 +17,16 @@ on:
types:
- completed
push:
branches: [ master, v3 ]
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, v3 ]
branches: [ master ]
schedule:
- cron: '34 1 * * 0'
jobs:
analyze:
name: analyze
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
@ -42,15 +42,12 @@ jobs:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup
uses: actions/setup-go@v3
with:
go-version: 1.17
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: init
uses: github/codeql-action/init@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -60,8 +57,8 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: autobuild
uses: github/codeql-action/autobuild@v2
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -74,5 +71,5 @@ jobs:
# make bootstrap
# make release
- name: analyze
uses: github/codeql-action/analyze@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -1,27 +1,66 @@
name: "dependabot-automerge"
name: "prautomerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
workflow_run:
workflows: ["prbuild"]
types:
- completed
permissions:
pull-requests: write
contents: write
pull-requests: write
jobs:
automerge:
Dependabot-Automerge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
# Contains workaround to execute if dependabot updates the PR by checking for the base branch in the linked PR
# The the github.event.workflow_run.event value is 'push' and not 'pull_request'
# dont work with multiple workflows when last returns success
if: >-
github.event.workflow_run.conclusion == 'success'
&& github.actor == 'dependabot[bot]'
&& github.event.sender.login == 'dependabot[bot]'
&& github.event.sender.type == 'Bot'
&& (github.event.workflow_run.event == 'pull_request'
|| (github.event.workflow_run.event == 'push' && github.event.workflow_run.pull_requests[0].base.ref == github.event.repository.default_branch ))
steps:
- name: metadata
id: metadata
uses: dependabot/fetch-metadata@v1.3.6
- name: Approve Changes and Merge changes if label 'dependencies' is set
uses: actions/github-script@v5
with:
github-token: "${{ secrets.TOKEN }}"
- name: merge
id: merge
if: ${{contains(steps.metadata.outputs.dependency-names, 'go.unistack.org')}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
console.log(context.payload.workflow_run);
var labelNames = await github.paginate(
github.issues.listLabelsOnIssue,
{
repo: context.repo.repo,
owner: context.repo.owner,
issue_number: context.payload.workflow_run.pull_requests[0].number,
},
(response) => response.data.map(
(label) => label.name
)
);
console.log(labelNames);
if (labelNames.includes('dependencies')) {
console.log('Found label');
await github.pulls.createReview({
repo: context.repo.repo,
owner: context.repo.owner,
pull_number: context.payload.workflow_run.pull_requests[0].number,
event: 'APPROVE'
});
console.log('Approved PR');
await github.pulls.merge({
repo: context.repo.repo,
owner: context.repo.owner,
pull_number: context.payload.workflow_run.pull_requests[0].number,
});
console.log('Merged PR');
}

View File

@ -3,20 +3,19 @@ on:
pull_request:
branches:
- master
- v3
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.16
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v2
- name: cache
uses: actions/cache@v3
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
@ -32,9 +31,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
uses: actions/checkout@v2
- name: lint
uses: golangci/golangci-lint-action@v3.4.0
uses: golangci/golangci-lint-action@v2
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.

88
env.go
View File

@ -1,4 +1,4 @@
package env
package env // import "go.unistack.org/micro-config-env/v3"
import (
"context"
@ -8,7 +8,7 @@ import (
"strconv"
"strings"
"dario.cat/mergo"
"github.com/imdario/mergo"
"go.unistack.org/micro/v3/config"
rutil "go.unistack.org/micro/v3/util/reflect"
)
@ -27,24 +27,11 @@ func (c *envConfig) Init(opts ...config.Option) error {
for _, o := range opts {
o(&c.opts)
}
if err := config.DefaultBeforeInit(c.opts.Context, c); err != nil && !c.opts.AllowFail {
return err
}
if err := config.DefaultAfterInit(c.opts.Context, c); err != nil && !c.opts.AllowFail {
return err
}
return nil
}
func (c *envConfig) Load(ctx context.Context, opts ...config.LoadOption) error {
if c.opts.SkipLoad != nil && c.opts.SkipLoad(ctx, c) {
return nil
}
if err := config.DefaultBeforeLoad(ctx, c); err != nil && !c.opts.AllowFail {
if err := config.DefaultBeforeLoad(ctx, c); err != nil {
return err
}
@ -57,23 +44,21 @@ func (c *envConfig) Load(ctx context.Context, opts ...config.LoadOption) error {
mopts = append(mopts, mergo.WithAppendSlice)
}
dst := c.opts.Struct
if options.Struct != nil {
dst = options.Struct
}
src, err := rutil.Zero(dst)
src, err := rutil.Zero(c.opts.Struct)
if err == nil {
if err = fillValues(ctx, reflect.ValueOf(src), c.opts.StructTag); err == nil {
err = mergo.Merge(dst, src, mopts...)
err = mergo.Merge(c.opts.Struct, src, mopts...)
}
}
if err != nil && !c.opts.AllowFail {
return err
if err != nil {
c.opts.Logger.Errorf(c.opts.Context, "env load err: %v", err)
if !c.opts.AllowFail {
return err
}
}
if err := config.DefaultAfterLoad(ctx, c); err != nil && !c.opts.AllowFail {
if err := config.DefaultAfterLoad(ctx, c); err != nil {
return err
}
@ -234,14 +219,13 @@ func (c *envConfig) setValues(ctx context.Context, valueOf reflect.Value) error
continue
}
tags, ok := field.Tag.Lookup(c.opts.StructTag)
tag, ok := field.Tag.Lookup(c.opts.StructTag)
if !ok {
continue
}
for _, tag := range strings.Split(tags, ",") {
if err := os.Setenv(tag, fmt.Sprintf("%v", value.Interface())); err != nil && !c.opts.AllowFail {
return err
}
if err := os.Setenv(tag, fmt.Sprintf("%v", value.Interface())); err != nil && !c.opts.AllowFail {
return err
}
}
@ -294,24 +278,16 @@ func fillValues(ctx context.Context, valueOf reflect.Value, structTag string) er
}
continue
}
tags, ok := field.Tag.Lookup(structTag)
tag, ok := field.Tag.Lookup(structTag)
if !ok {
continue
}
val, ok := os.LookupEnv(tag)
if !ok {
continue
}
var eval string
for _, tag := range strings.Split(tags, ",") {
if val, ok := os.LookupEnv(tag); !ok {
continue
} else {
eval = val
}
}
if eval == "" {
continue
}
if err := fillValue(ctx, value, eval); err != nil {
if err := fillValue(ctx, value, val); err != nil {
return err
}
}
@ -320,26 +296,18 @@ func fillValues(ctx context.Context, valueOf reflect.Value, structTag string) er
}
func (c *envConfig) Save(ctx context.Context, opts ...config.SaveOption) error {
if c.opts.SkipSave != nil && c.opts.SkipSave(ctx, c) {
return nil
}
options := config.NewSaveOptions(opts...)
if err := config.DefaultBeforeSave(ctx, c); err != nil && !c.opts.AllowFail {
if err := config.DefaultBeforeSave(ctx, c); err != nil {
return err
}
dst := c.opts.Struct
if options.Struct != nil {
dst = options.Struct
if err := c.setValues(ctx, reflect.ValueOf(c.opts.Struct)); err != nil {
c.opts.Logger.Errorf(c.opts.Context, "env save error: %v", err)
if !c.opts.AllowFail {
return err
}
}
if err := c.setValues(ctx, reflect.ValueOf(dst)); err != nil && !c.opts.AllowFail {
return err
}
if err := config.DefaultAfterSave(ctx, c); err != nil && !c.opts.AllowFail {
if err := config.DefaultAfterSave(ctx, c); err != nil {
return err
}

View File

@ -4,14 +4,12 @@ import (
"context"
"os"
"testing"
"time"
"go.unistack.org/micro/v3/config"
rutil "go.unistack.org/micro/v3/util/reflect"
)
type Config struct {
StringValue string `env:"STRING_VALUE,STRING_VALUE2"`
StringValue string `env:"STRING_VALUE"`
BoolValue bool `env:"BOOL_VALUE"`
StringSlice []string `env:"STRING_SLICE"`
IntSlice []int `env:"INT_SLICE"`
@ -19,72 +17,7 @@ type Config struct {
MapIntValue map[string]int `env:"MAP_INT"`
}
func TestMerge(t *testing.T) {
defer func() {
for _, v := range []string{"STRING_VALUE", "BOOL_VALUE", "STRING_SLICE", "INT_SLICE", "MAP_STRING", "MAP_INT"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
}()
ctx := context.Background()
type Nested struct {
Name string `env:"NAME_VALUE"`
}
type Cfg struct {
Name string `env:"NAME_VALUE"`
Nested Nested
}
conf := &Cfg{}
cfg := NewConfig(config.Struct(conf))
if err := cfg.Init(); err != nil {
t.Fatal(err)
}
if err := cfg.Load(ctx, config.LoadOverride(true), config.LoadAppend(true)); err != nil {
t.Fatal(err)
}
w, err := cfg.Watch(ctx, config.WatchInterval(50*time.Millisecond, 500*time.Millisecond))
defer func() {
if err := w.Stop(); err != nil {
t.Fatal(err)
}
}()
if err != nil {
t.Fatal(err)
}
os.Setenv("NAME_VALUE", "after")
changes, err := w.Next()
if err != nil {
t.Fatal(err)
}
for k, v := range changes {
if err := rutil.SetFieldByPath(conf, v, k); err != nil {
t.Fatal(err)
}
}
if conf.Name != "after" || conf.Nested.Name != "after" {
t.Fatalf("changes %#+v not applied to %#+v", changes, conf)
}
}
func TestLoad(t *testing.T) {
defer func() {
for _, v := range []string{"STRING_VALUE", "STRING_VALUE2", "BOOL_VALUE", "STRING_SLICE", "INT_SLICE", "MAP_STRING", "MAP_INT"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
}()
ctx := context.Background()
conf := &Config{StringValue: "before_load"}
cfg := NewConfig(config.Struct(conf))
@ -131,22 +64,10 @@ func TestLoad(t *testing.T) {
t.Fatalf("something wrong with env config: %#+v", conf.MapIntValue)
}
for _, v := range []string{"STRING_VALUE", "STRING_VALUE2", "BOOL_VALUE", "STRING_SLICE", "INT_SLICE", "MAP_STRING", "MAP_INT"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
t.Logf("cfg %#+v", conf)
}
func TestSave(t *testing.T) {
defer func() {
for _, v := range []string{"STRING_VALUE", "STRING_VALUE2", "BOOL_VALUE", "STRING_SLICE", "INT_SLICE", "MAP_STRING", "MAP_INT"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
}()
ctx := context.Background()
conf := &Config{StringValue: "MICRO_CONFIG_ENV"}
cfg := NewConfig(config.Struct(conf))
@ -182,59 +103,4 @@ func TestSave(t *testing.T) {
t.Fatalf("env value %s=%s set", tv, v)
}
}
for _, v := range []string{"STRING_VALUE", "STRING_VALUE2", "BOOL_VALUE", "STRING_SLICE", "INT_SLICE", "MAP_STRING", "MAP_INT"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
}
func TestLoadMultiple(t *testing.T) {
defer func() {
for _, v := range []string{"STRING_VALUE", "STRING_VALUE2", "BOOL_VALUE", "STRING_SLICE", "INT_SLICE", "MAP_STRING", "MAP_INT"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
}()
ctx := context.Background()
conf := &Config{StringValue: "before_load"}
cfg := NewConfig(config.Struct(conf))
if err := cfg.Init(); err != nil {
t.Fatal(err)
}
if err := cfg.Load(ctx, config.LoadOverride(true), config.LoadAppend(true)); err != nil {
t.Fatal(err)
}
if conf.StringValue != "before_load" {
t.Fatalf("something wrong with env config: %#+v", conf)
}
os.Setenv("STRING_VALUE", "STRING_VALUE1")
os.Setenv("STRING_VALUE2", "STRING_VALUE2")
defer func() {
for _, v := range []string{"STRING_VALUE", "STRING_VALUE2"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
}()
if err := cfg.Load(ctx, config.LoadOverride(true), config.LoadAppend(true)); err != nil {
t.Fatal(err)
}
if conf.StringValue != "STRING_VALUE2" {
t.Fatalf("something wrong with env config: %#+v", conf)
}
for _, v := range []string{"STRING_VALUE", "STRING_VALUE2", "BOOL_VALUE", "STRING_SLICE", "INT_SLICE", "MAP_STRING", "MAP_INT"} {
if err := os.Unsetenv(v); err != nil {
t.Fatal(err)
}
}
}

10
go.mod
View File

@ -1,10 +1,8 @@
module go.unistack.org/micro-config-env/v3
module go.unistack.orgmicro-config-env/v3
go 1.20
go 1.16
require (
dario.cat/mergo v1.0.0
go.unistack.org/micro/v3 v3.10.44
github.com/imdario/mergo v0.3.12
go.unistack.org/micro/v3 v3.8.5
)
require github.com/google/uuid v1.6.0 // indirect

35
go.sum
View File

@ -1,9 +1,28 @@
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
go.unistack.org/micro/v3 v3.10.44 h1:Vgyy9BrJOSdFvo29/klrgIBE/Nme9E8udPAljos34o0=
go.unistack.org/micro/v3 v3.10.44/go.mod h1:erMgt3Bl7vQQ0e9UpQyR5NlLiZ9pKeEJ9+1tfYFaqUg=
github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg=
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
go.unistack.org/micro-proto/v3 v3.1.0 h1:q39FwjFiRZn+Ux/tt+d3bJTmDtsQQWa+3SLYVo1vLfA=
go.unistack.org/micro-proto/v3 v3.1.0/go.mod h1:DpRhYCBXlmSJ/AAXTmntvlh7kQkYU6eFvlmYAx4BQS8=
go.unistack.org/micro/v3 v3.8.5 h1:DIYWRsQF+NPhKZP45sCtNsUhaRw6u2+Ps7U+pKU7i3s=
go.unistack.org/micro/v3 v3.8.5/go.mod h1:KMMmOmbgo/D52/rCAbqeKbBsgEEbSKM69he54J3ZIuA=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=