Skip to content

Commit

Permalink
Ensure first character of delimiter is not a value terminator (#96)
Browse files Browse the repository at this point in the history
  • Loading branch information
sethvargo authored Apr 11, 2024
1 parent 9c1562d commit de7f637
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 22 deletions.
17 changes: 13 additions & 4 deletions 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 dist/kv.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ export declare function joinKVString(input: KVPair, separator?: string): string;
* string.
*
* @param input KVPair to serialize.
* @param rand String of random characters to use; override for testing.
*/
export declare function joinKVStringForGCloud(input: KVPair): string;
export declare function joinKVStringForGCloud(input: KVPair, rand?: string): string;
/**
* parseKVString parses a string of the format "KEY1=VALUE1,KEY2=VALUE2" or
* "KEY1=VALUE1\nKEY2=VALUE2". Keys or values that contain a separator must be
Expand Down
15 changes: 8 additions & 7 deletions docs/modules/kv.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ ___

### joinKVStringForGCloud

**joinKVStringForGCloud**(`input`): `string`
**joinKVStringForGCloud**(`input`, `rand?`): `string`

joinKVStringForGCloud creates a string suitable for using with gcloud by
choosing a custom escape delimiter sequence that does not exist in the input
Expand All @@ -68,14 +68,15 @@ string.
| Name | Type | Description |
| :------ | :------ | :------ |
| `input` | [`KVPair`](kv.md#kvpair) | KVPair to serialize. |
| `rand` | `string` | String of random characters to use; override for testing. |

#### Returns

`string`

#### Defined in

[kv.ts:50](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L50)
[kv.ts:51](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L51)

___

Expand All @@ -99,7 +100,7 @@ the contents are parsed as a subset of YAML.

#### Defined in

[kv.ts:158](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L158)
[kv.ts:172](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L172)

___

Expand Down Expand Up @@ -129,7 +130,7 @@ List of key=value pairs.

#### Defined in

[kv.ts:193](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L193)
[kv.ts:207](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L207)

___

Expand All @@ -154,7 +155,7 @@ is trimmed.

#### Defined in

[kv.ts:89](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L89)
[kv.ts:103](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L103)

___

Expand All @@ -178,7 +179,7 @@ results (with kvString taking precedence).

#### Defined in

[kv.ts:264](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L264)
[kv.ts:278](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L278)

___

Expand All @@ -201,4 +202,4 @@ for testing.

#### Defined in

[kv.ts:237](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L237)
[kv.ts:251](https://github.com/google-github-actions/actions-utils/blob/main/src/kv.ts#L251)
22 changes: 18 additions & 4 deletions src/kv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,42 @@ export function joinKVString(input: KVPair, separator = ','): string {
* string.
*
* @param input KVPair to serialize.
* @param rand String of random characters to use; override for testing.
*/
export function joinKVStringForGCloud(input: KVPair): string {
export function joinKVStringForGCloud(
input: KVPair,
rand = randomBytes(128).toString('hex'),
): string {
const initial = Object.entries(input).join('');

if (initial === '') {
return '';
}

const rand = randomBytes(128).toString('hex');
let delim = '';

// Build an increasingly longer delimiter.
for (let i = 0; i < rand.length; i++) {
delim += rand[i];
const ch = rand[i];

// The first character in the delimiter cannot match the last character of
// any values because gcloud parses left-to-right:
//
// https://github.com/google-github-actions/deploy-cloudrun/issues/503
//
if (delim === '' && Object.values(input).some((v) => v.endsWith(ch))) {
continue;
}

delim += ch;
if (initial.includes(delim)) {
continue;
}

// If we got this far, then the delimiter is not found in the string.
break;
}
if (initial.includes(delim)) {
if (delim === '' || initial.includes(delim)) {
throw new Error(
`Something extremely probabilistically unlikely has occured - one of ` +
`the KV pairs exactly matched 128 randomly-generated bytes. Please ` +
Expand Down
15 changes: 10 additions & 5 deletions tests/kv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,29 @@ describe('kv', { concurrency: true }, async () => {
{
name: 'empty',
input: {},
expected: /^$/,
expected: '',
},
{
name: 'single entry',
input: { FOO: 'bar' },
expected: /\^[a-f0-9]+\^FOO=bar/,
expected: '^d^FOO=bar',
},
{
name: 'value ends with delim',
input: { HELLO: 'world', GOODBYE: 'mars' },
expected: '^e^HELLO=worldeGOODBYE=mars',
},
{
name: 'iterates',
input: { abcdefghijklmnopqrstuvwxyz: '01234567890' },
expected: /\^[a-f0-9]{2,}\^abcdefghijklmnopqrstuvwxyz=01234567890/,
expected: '^dea^abcdefghijklmnopqrstuvwxyz=01234567890',
},
];

for await (const tc of cases) {
await suite.test(tc.name, async () => {
const actual = joinKVStringForGCloud(tc.input as KVPair);
assert.match(actual, tc.expected);
const actual = joinKVStringForGCloud(tc.input as KVPair, 'deab');
assert.deepStrictEqual(actual, tc.expected);
});
}
});
Expand Down

0 comments on commit de7f637

Please sign in to comment.