Skip to content

Commit 8d4e06c

Browse files
nervghalexey-igrychev
authored andcommitted
feat(config): add .Files.Exists and .Files.IsDir Go template functions
Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
1 parent 2a3da12 commit 8d4e06c

23 files changed

+2474
-174
lines changed

docs/_data/werf_giterminism_yaml.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ directives:
4545
- name: allowUncommittedFiles
4646
value: "[ glob, ... ]"
4747
description:
48-
en: Read the certain configuration files from the project directory despite the state in git repository and .gitignore rules (using .Files.Get and .Files.Glob functions)
49-
ru: Читать определённые конфигурационные файлы из директории проекта, не сверяя контент с файлами текущего коммита и игнорируя исключения в .gitignore (используя функции .Files.Get и .Files.Glob)
48+
en: Read the certain configuration files from the project directory despite the state in git repository and .gitignore rules (using .Files.Exists, .Files.Get, .Files.Glob, and .Files.IsDir functions)
49+
ru: Читать определённые конфигурационные файлы из директории проекта, не сверяя контент с файлами текущего коммита и игнорируя исключения в .gitignore (используя функции .Files.Exists, .Files.Get, .Files.Glob и .Files.IsDir)
5050
- name: secrets
5151
description:
5252
en: The rules for using secret values

docs/pages_en/reference/werf_yaml_template_engine.md

+26
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,19 @@ __Syntax__:
223223
224224
### project files
225225

226+
#### .Files.Exists
227+
228+
The function `.Files.Exists` checks existence of a file (regular/directory) in project and returns the result `true` or `false`.
229+
230+
__Syntax__:
231+
{% raw %}
232+
```yaml
233+
{{ .Files.Exists "<FILE_PATH>" }}
234+
```
235+
{% endraw %}
236+
237+
> By default, the use of files that have non-committed changes is not allowed by giterminism (read more about it [here]({{ "usage/project_configuration/giterminism.html" | true_relative_url }}))
238+
226239
#### .Files.Get
227240

228241
The function `.Files.Get` gets a certain project file content.
@@ -336,6 +349,19 @@ ansible:
336349
```
337350
{% endraw %}
338351

352+
#### .Files.IsDir
353+
354+
The function `.Files.IsDir` checks path is a directory and returns `true` or `false`.
355+
356+
__Syntax__:
357+
{% raw %}
358+
```yaml
359+
{{ .Files.IsDir "<PATH>" }}
360+
```
361+
{% endraw %}
362+
363+
> By default, the use of files that have non-committed changes is not allowed by giterminism (read more about it [here]({{ "usage/project_configuration/giterminism.html" | true_relative_url }}))
364+
339365
### others
340366

341367
#### required

docs/pages_ru/reference/werf_yaml_template_engine.md

+26
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,19 @@ __Синтаксис__:
223223
224224
### Файлы проекта
225225

226+
#### .Files.Exists
227+
228+
Функция `.Files.Exists` проверят наличие файла/директории в рамках проекта и возвращает результат `true` или `false`.
229+
230+
__Синтаксис__:
231+
{% raw %}
232+
```yaml
233+
{{ .Files.Exists "<FILE_PATH>" }}
234+
```
235+
{% endraw %}
236+
237+
> По умолчанию, использование файлов, которые имеют незакоммиченные изменения, запрещено гитерминизмом (подробнее об этом в [статье]({{ "usage/project_configuration/giterminism.html" | true_relative_url }}))
238+
226239
#### .Files.Get
227240

228241
Функция `.Files.Get` получает содержимое определенного файла проекта.
@@ -336,6 +349,19 @@ ansible:
336349
```
337350
{% endraw %}
338351

352+
#### .Files.IsDir
353+
354+
Функция `.Files.IsDir` проверят, является ли путь директорией и возвращает результат `true` или `false`.
355+
356+
__Синтаксис__:
357+
{% raw %}
358+
```yaml
359+
{{ .Files.IsDir "<PATH>" }}
360+
```
361+
{% endraw %}
362+
363+
> По умолчанию, использование файлов, которые имеют незакоммиченные изменения, запрещено гитерминизмом (подробнее об этом в [статье]({{ "usage/project_configuration/giterminism.html" | true_relative_url }}))
364+
339365
### Другие
340366

341367
#### required

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ require (
7575
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0
7676
go.opentelemetry.io/otel/sdk v1.24.0
7777
go.opentelemetry.io/otel/trace v1.24.0
78+
go.uber.org/mock v0.5.0
7879
golang.org/x/crypto v0.31.0
7980
golang.org/x/net v0.33.0
8081
golang.org/x/sys v0.28.0

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,8 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
15781578
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
15791579
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
15801580
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
1581+
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
1582+
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
15811583
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
15821584
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
15831585
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=

pkg/config/parser.go

+16
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,22 @@ func (f files) Glob(pattern string) map[string]interface{} {
375375
}
376376
}
377377

378+
func (f files) Exists(relPath string) bool {
379+
exist, err := f.giterminismManager.FileReader().ConfigGoTemplateFilesExists(f.ctx, relPath)
380+
if err != nil {
381+
panic(err.Error())
382+
}
383+
return exist
384+
}
385+
386+
func (f files) IsDir(relPath string) bool {
387+
exist, err := f.giterminismManager.FileReader().ConfigGoTemplateFilesIsDir(f.ctx, relPath)
388+
if err != nil {
389+
panic(err.Error())
390+
}
391+
return exist
392+
}
393+
378394
func splitContent(content []byte) (docsContents [][]byte) {
379395
const (
380396
stateLineBegin = "stateLineBegin"

pkg/git_repo/git_repo.go

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ const (
3636
DirectoryArchive ArchiveType = "directory"
3737
)
3838

39+
//go:generate mockgen -source git_repo.go -package mock -destination ../../test/mock/git_repo.go
40+
3941
type GitRepo interface {
4042
String() string
4143
GetName() string

pkg/giterminism_manager/file_reader/config.go

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ func (r FileReader) readConfig(ctx context.Context, customRelPath string) (strin
6363
for _, configPath := range configRelPathList {
6464
data, err := r.ReadAndCheckConfigurationFile(ctx, configPath, func(_ string) bool {
6565
return r.giterminismConfig.IsUncommittedConfigAccepted()
66+
}, func(path string) (bool, error) {
67+
return r.IsRegularFileExist(ctx, path)
6668
})
6769
if err != nil {
6870
if errors.As(err, &FileNotFoundInProjectDirectoryError{}) ||

pkg/giterminism_manager/file_reader/config_go_template.go

+48-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package file_reader
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"path/filepath"
78
)
@@ -31,10 +32,56 @@ func (r FileReader) ConfigGoTemplateFilesGlob(ctx context.Context, glob string)
3132
}
3233

3334
func (r FileReader) ConfigGoTemplateFilesGet(ctx context.Context, relPath string) ([]byte, error) {
34-
data, err := r.ReadAndCheckConfigurationFile(ctx, relPath, r.giterminismConfig.UncommittedConfigGoTemplateRenderingFilePathMatcher().IsPathMatched)
35+
data, err := r.ReadAndCheckConfigurationFile(ctx, relPath,
36+
r.giterminismConfig.UncommittedConfigGoTemplateRenderingFilePathMatcher().IsPathMatched,
37+
func(path string) (bool, error) {
38+
return r.IsRegularFileExist(ctx, path)
39+
})
3540
if err != nil {
3641
return nil, fmt.Errorf("{{ .Files.Get %q }}: %w", relPath, err)
3742
}
3843

3944
return data, nil
4045
}
46+
47+
func (r FileReader) ConfigGoTemplateFilesExists(ctx context.Context, relPath string) (bool, error) {
48+
ok, err := r.CheckConfigurationFileExistenceAndAcceptance(ctx, relPath,
49+
r.giterminismConfig.UncommittedConfigGoTemplateRenderingFilePathMatcher().IsPathMatched,
50+
func(path string) (bool, error) {
51+
return r.IsFileExist(ctx, path)
52+
})
53+
if err != nil {
54+
switch {
55+
case errors.As(err, &UntrackedFilesError{}),
56+
errors.As(err, &UncommittedFilesError{}),
57+
errors.As(err, &FileNotAcceptedError{}),
58+
errors.As(err, &FileNotFoundInProjectDirectoryError{}),
59+
errors.As(err, &FileNotFoundInProjectRepositoryError{}):
60+
return false, nil
61+
default:
62+
return false, fmt.Errorf("{{ .Files.Exists %q }}: %w", relPath, err)
63+
}
64+
}
65+
return ok, nil
66+
}
67+
68+
func (r FileReader) ConfigGoTemplateFilesIsDir(ctx context.Context, relPath string) (bool, error) {
69+
ok, err := r.CheckConfigurationFileExistenceAndAcceptance(ctx, relPath,
70+
r.giterminismConfig.UncommittedConfigGoTemplateRenderingFilePathMatcher().IsPathMatched,
71+
func(path string) (bool, error) {
72+
return r.IsDirectoryExist(ctx, path)
73+
})
74+
if err != nil {
75+
switch {
76+
case errors.As(err, &UntrackedFilesError{}),
77+
errors.As(err, &UncommittedFilesError{}),
78+
errors.As(err, &FileNotAcceptedError{}),
79+
errors.As(err, &FileNotFoundInProjectDirectoryError{}),
80+
errors.As(err, &FileNotFoundInProjectRepositoryError{}):
81+
return false, nil
82+
default:
83+
return false, fmt.Errorf("{{ .Files.IsDir %q }}: %w", relPath, err)
84+
}
85+
}
86+
return ok, nil
87+
}

0 commit comments

Comments
 (0)