Skip to content

Commit

Permalink
fix(flags): Handle space separated and double quoted multi-valued fla…
Browse files Browse the repository at this point in the history
…gs (#236)

* add tokenization of flags

* fix lint and unit test

* update dist folder

* update dist folder

* fix lint and unit test

---------

Co-authored-by: Gulom Alimov <[email protected]>
  • Loading branch information
Googlom and Gulom Alimov authored Jan 15, 2025
1 parent f8f9ede commit 374680f
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 3 deletions.
35 changes: 34 additions & 1 deletion dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/piper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getDefaultConfig, readContextConfig, createCheckIfStepActiveMaps } from
import { loadPipelineEnv, exportPipelineEnv } from './pipelineEnv'
import { cleanupContainers, runContainers } from './docker'
import { isEnterpriseStep, onGitHubEnterprise } from './enterprise'
import { tokenize } from './utils'

// Global runtime variables that is accessible within a single action execution
export const internalActionVariables = {
Expand Down Expand Up @@ -44,7 +45,7 @@ export async function run (): Promise<void> {
}
}
if (actionCfg.stepName !== '') {
const flags = actionCfg.flags.split(' ')
const flags = tokenize(actionCfg.flags)
const contextConfig = await readContextConfig(actionCfg.stepName, flags)
await runContainers(actionCfg, contextConfig)
await executePiper(actionCfg.stepName, flags)
Expand Down
22 changes: 22 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// tokenize functions splits a string of CLI flags by whitespace, additionally handling double-quoted
// and space separated string values
export function tokenize (input: string): string[] {
// Regular expression to find quoted strings or sequences of non-whitespace characters
const regex = /"([^"]*)"|\S+/g

const tokens: string[] = []
let match: RegExpExecArray | null

// Use the exec method to find all matches in the input string
while ((match = regex.exec(input)) !== null) {
// match[1] will hold the matched content inside quotes if it exists,
// otherwise use match[0] which covers the non-quoted matches
if (match[1] !== undefined) {
tokens.push(match[1]) // Pushes the inside of the quotes to the array
} else {
tokens.push(match[0]) // Pushes the non-quoted match to the array
}
}

return tokens
}
33 changes: 33 additions & 0 deletions test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { tokenize } from '../src/utils'

describe('utils.tokenize', () => {
it('should handle normal unquoted words', () => {
const result = tokenize('--flag1 flag1value --anotherFlag')
expect(result).toEqual(['--flag1', 'flag1value', '--anotherFlag'])
})

it('should handle single quoted group', () => {
const result = tokenize('--flag1 "multi value"')
expect(result).toEqual(['--flag1', 'multi value'])
})

it('should handle multiple quoted groups', () => {
const result = tokenize('--flag1 "multi value" --anotherFlag "another multi value" --flag333')
expect(result).toEqual(['--flag1', 'multi value', '--anotherFlag', 'another multi value', '--flag333'])
})

it('should handle empty quotes', () => {
const result = tokenize('--flag1 "" --flag2')
expect(result).toEqual(['--flag1', '', '--flag2'])
})

it('should correctly tokenize empty input', () => {
const result = tokenize('')
expect(result).toEqual([])
})

it('should handle quotes without spaces in between', () => {
const result = tokenize('"first""second""third"')
expect(result).toEqual(['first', 'second', 'third'])
})
})

0 comments on commit 374680f

Please sign in to comment.