diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cb0d0e..4a3fa0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: sources: | **/*.json;!**/*.DEV.json;!**/vars.json => _tmp/*.json **/*.xml;!**.dev.xml => _tmp/*.xml - **/*.YML => _tmp/*.yml + **/*.YML;!**/*vars.yml => _tmp/*.yml variables: > [ ${{ toJSON(vars) }}, @@ -107,6 +107,7 @@ jobs: recursive: true transforms: true case-insensitive-paths: true + include-dot-paths: true env: ENV_VARS: '{ "var4": "env_value4" }' diff --git a/CHANGELOG.md b/CHANGELOG.md index 53ee36f..db917b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v1.2.0 - Upgrade package `@qetza/replacetokens` to `1.7.0`. - Add support for case insensitive path matching in _sources_ and _variables_. +- Add support for matching directories and files starting with a dot in _sources_ and _variables_. ## v1.1.2 - Change telemetry provider. diff --git a/README.md b/README.md index 3d8f677..592d1f1 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,12 @@ Please refer to the [release page](https://github.com/qetza/replacetokens-action # Optional. Default: ignore if-no-files-found: '' + # Include directories and files starting with a dot '.' in glob matching results for sources + # and additionalVariables. + # + # Optional. Default: false + include-dot-paths: '' + # The log level. # # Accepted values: diff --git a/action.yml b/action.yml index b981670..91867f2 100644 --- a/action.yml +++ b/action.yml @@ -54,7 +54,7 @@ inputs: Accepted values: - auto: detect encoding using js-chardet - any value supported by iconv-lite - default: auto + default: 'auto' escape: description: > Character escape type to apply on each value. @@ -71,6 +71,9 @@ inputs: if-no-files-found: description: 'The behavior if no files are found: ignore, warn, error.' default: 'ignore' + include-dot-paths: + description: 'Include directories and files starting with a dot ''.'' in glob matching results for sources and additionalVariables.' + default: 'false' log-level: description: > The log level. diff --git a/dist/index.js b/dist/index.js index 74e8db9..0fcef1b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -63665,7 +63665,8 @@ async function run() { recursive: core.getBooleanInput('recursive'), root: core.getInput('root'), sources: { - caseInsensitive: core.getBooleanInput('case-insensitive-paths') + caseInsensitive: core.getBooleanInput('case-insensitive-paths'), + dot: core.getBooleanInput('include-dot-paths') }, token: { pattern: getChoiceInput('token-pattern', [ @@ -63717,7 +63718,7 @@ async function run() { }; // load variables const separator = core.getInput('separator') || rt.Defaults.Separator; - const variables = await getVariables(options.root, separator, options.sources.caseInsensitive); + const variables = await getVariables(options.root, separator, options.sources.caseInsensitive, options.sources.dot); // set telemetry attributes telemetryEvent.setAttributes({ sources: sources.length, @@ -63728,6 +63729,7 @@ async function run() { escape: options.escape.type, 'escape-char': options.escape.escapeChar, 'if-no-files-found': ifNoFilesFound, + 'include-dot-paths': options.sources.dot, 'log-level': logLevelStr, 'missing-var-action': options.missing.action, 'missing-var-default': options.missing.default, @@ -63806,12 +63808,13 @@ function getSources() { var variableFilesCount = 0; var variablesEnvCount = 0; var inlineVariablesCount = 0; -async function getVariables(root, separator, caseInsensitive) { +async function getVariables(root, separator, caseInsensitive, dot) { const input = core.getInput('variables', { required: true, trimWhitespace: true }) || ''; if (!input) return {}; return await rt.loadVariables(getVariablesFromJson(input), { caseInsensitive: caseInsensitive, + dot: dot, normalizeWin32: true, root: root, separator: separator diff --git a/src/main.ts b/src/main.ts index 4e0ee06..f7248f3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -64,7 +64,8 @@ export async function run(): Promise { recursive: core.getBooleanInput('recursive'), root: core.getInput('root'), sources: { - caseInsensitive: core.getBooleanInput('case-insensitive-paths') + caseInsensitive: core.getBooleanInput('case-insensitive-paths'), + dot: core.getBooleanInput('include-dot-paths') }, token: { pattern: @@ -116,7 +117,12 @@ export async function run(): Promise { // load variables const separator = core.getInput('separator') || rt.Defaults.Separator; - const variables = await getVariables(options.root, separator, options.sources!.caseInsensitive); + const variables = await getVariables( + options.root, + separator, + options.sources!.caseInsensitive, + options.sources!.dot + ); // set telemetry attributes telemetryEvent.setAttributes({ @@ -128,6 +134,7 @@ export async function run(): Promise { escape: options.escape!.type, 'escape-char': options.escape!.escapeChar, 'if-no-files-found': ifNoFilesFound, + 'include-dot-paths': options.sources!.dot, 'log-level': logLevelStr, 'missing-var-action': options.missing!.action, 'missing-var-default': options.missing!.default, @@ -219,13 +226,15 @@ var inlineVariablesCount = 0; async function getVariables( root?: string, separator?: string, - caseInsensitive?: boolean + caseInsensitive?: boolean, + dot?: boolean ): Promise<{ [key: string]: string }> { const input = core.getInput('variables', { required: true, trimWhitespace: true }) || ''; if (!input) return {}; return await rt.loadVariables(getVariablesFromJson(input), { caseInsensitive: caseInsensitive, + dot: dot, normalizeWin32: true, root: root, separator: separator diff --git a/tests/data/vars.yml b/tests/data/.vars/.vars.yml similarity index 100% rename from tests/data/vars.yml rename to tests/data/.vars/.vars.yml diff --git a/tests/run.test.ts b/tests/run.test.ts index 35f4980..caeb382 100644 --- a/tests/run.test.ts +++ b/tests/run.test.ts @@ -205,7 +205,8 @@ describe('run', () => { recursive: false, root: '', sources: { - caseInsensitive: false + caseInsensitive: false, + dot: false }, token: { pattern: rt.TokenPatterns.Default, @@ -247,7 +248,7 @@ describe('run', () => { expect(debugSpy).toHaveBeenCalledWith( expect.stringMatching( - /\[\{"eventType":"TokensReplaced","application":"replacetokens-action","version":"1\.\d+\.\d+","account":"c054bf9f6127dc352a184a29403ac9114f6c2a8e27cb467197cdfc1c3df119e4","pipeline":"59830ebc3a4184110566bf1a290d08473dfdcbd492ce498b14cd1a5e2fa2e441","host":"server","os":"Windows","sources":3,"add-bom":false,"case-insensitive-paths":false,"chars-to-escape":"","encoding":"auto","escape":"auto","escape-char":"","if-no-files-found":"ignore","log-level":"info","missing-var-action":"none","missing-var-default":"","missing-var-log":"warn","recusrive":false,"separator":"\.","token-pattern":"default","token-prefix":"","token-suffix":"","transforms":false,"transforms-prefix":"\(","transforms-suffix":"\)","variable-files":0,"variable-envs":0,"inline-variables":0,"output-defaults":1,"output-files":2,"output-replaced":3,"output-tokens":4,"output-transforms":5,"result":"success","duration":\d+(?:\.\d+)?}]/ + /\[\{"eventType":"TokensReplaced","application":"replacetokens-action","version":"1\.\d+\.\d+","account":"c054bf9f6127dc352a184a29403ac9114f6c2a8e27cb467197cdfc1c3df119e4","pipeline":"59830ebc3a4184110566bf1a290d08473dfdcbd492ce498b14cd1a5e2fa2e441","host":"server","os":"Windows","sources":3,"add-bom":false,"case-insensitive-paths":false,"chars-to-escape":"","encoding":"auto","escape":"auto","escape-char":"","if-no-files-found":"ignore","include-dot-paths":false,"log-level":"info","missing-var-action":"none","missing-var-default":"","missing-var-log":"warn","recusrive":false,"separator":"\.","token-pattern":"default","token-prefix":"","token-suffix":"","transforms":false,"transforms-prefix":"\(","transforms-suffix":"\)","variable-files":0,"variable-envs":0,"inline-variables":0,"output-defaults":1,"output-files":2,"output-replaced":3,"output-tokens":4,"output-transforms":5,"result":"success","duration":\d+(?:\.\d+)?}]/ ) ); }); @@ -324,7 +325,8 @@ describe('run', () => { separator: rt.Defaults.Separator, normalizeWin32: true, root: '', - caseInsensitive: false + caseInsensitive: false, + dot: false }); expect(replaceTokenSpy).toHaveBeenCalledWith(expect.anything(), expect.any(Function), expect.anything()); @@ -352,7 +354,8 @@ describe('run', () => { separator: rt.Defaults.Separator, normalizeWin32: true, root: '', - caseInsensitive: false + caseInsensitive: false, + dot: false }); expect(replaceTokenSpy).toHaveBeenCalledWith(expect.anything(), expect.any(Function), expect.anything()); @@ -380,7 +383,8 @@ describe('run', () => { separator: rt.Defaults.Separator, normalizeWin32: true, root: '', - caseInsensitive: false + caseInsensitive: false, + dot: false }); expect(replaceTokenSpy).toHaveBeenCalledWith(expect.anything(), expect.any(Function), expect.anything()); @@ -414,7 +418,8 @@ describe('run', () => { separator: rt.Defaults.Separator, normalizeWin32: true, root: '', - caseInsensitive: false + caseInsensitive: false, + dot: false }); expect(replaceTokenSpy).toHaveBeenCalledWith(expect.anything(), expect.any(Function), expect.anything()); @@ -452,7 +457,8 @@ describe('run', () => { separator: rt.Defaults.Separator, normalizeWin32: true, root: '', - caseInsensitive: false + caseInsensitive: false, + dot: false } ); @@ -486,7 +492,8 @@ describe('run', () => { separator: rt.Defaults.Separator, normalizeWin32: true, root: '', - caseInsensitive: false + caseInsensitive: false, + dot: false }); expect(replaceTokenSpy).toHaveBeenCalledWith(expect.anything(), expect.any(Function), expect.anything()); @@ -650,6 +657,41 @@ describe('run', () => { ); }); + it('include-dot-paths', async () => { + // arrange + getBooleanInputSpy.mockImplementation(name => { + switch (name) { + case 'include-dot-paths': + return true; + default: + return false; + } + }); + + getInputSpy.mockImplementation(name => { + switch (name) { + case 'variables': + return '{}'; + default: + return ''; + } + }); + + // act + await run(); + + // assert + expect(setFailedSpy).not.toHaveBeenCalled(); + + expect(loadVariablesSpy).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ dot: true })); + + expect(replaceTokenSpy).toHaveBeenCalledWith( + expect.anything(), + expect.any(Function), + expect.objectContaining({ sources: expect.objectContaining({ dot: true }) }) + ); + }); + it('log-level: debug', async () => { // arrange getInputSpy.mockImplementation(name => { @@ -993,12 +1035,7 @@ describe('run', () => { // assert expect(setFailedSpy).not.toHaveBeenCalled(); - expect(loadVariablesSpy).toHaveBeenCalledWith(['{}'], { - separator: ':', - normalizeWin32: true, - root: '', - caseInsensitive: false - }); + expect(loadVariablesSpy).toHaveBeenCalledWith(['{}'], expect.objectContaining({ separator: ':' })); expect(replaceTokenSpy).toHaveBeenCalledWith(expect.anything(), expect.any(Function), expect.anything()); });