Skip to content

Commit

Permalink
[eas-cli] more branch mapping utility (#1957)
Browse files Browse the repository at this point in the history
* [eas-cli] more branch mapping utility

* update CHANGELOG.md
  • Loading branch information
quinlanj authored Jul 28, 2023
1 parent 2cece65 commit 05799ab
Show file tree
Hide file tree
Showing 6 changed files with 451 additions and 113 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ This is the log of notable changes to EAS CLI and related packages.

### 🧹 Chores

- More branch mapping utility. ([#1957](https://github.com/expo/eas-cli/pull/1957) by [@quinlanj](https://github.com/quinlanj))

## [3.17.1](https://github.com/expo/eas-cli/releases/tag/v3.17.1) - 2023-07-27

### 🧹 Chores
Expand Down
2 changes: 1 addition & 1 deletion packages/eas-cli/src/channel/__tests__/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const testUpdateBranch1: UpdateBranchObject = {
__typename: 'UpdateBranch',
};

const testUpdateBranch2: UpdateBranchObject = {
export const testUpdateBranch2: UpdateBranchObject = {
id: '6941a8dd-5c0a-48bc-8876-f49c88ed419f',
name: 'production',
updateGroups: [
Expand Down
31 changes: 31 additions & 0 deletions packages/eas-cli/src/channel/branch-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ export type BranchMapping = {
}[];
};

export function getAlwaysTrueBranchMapping(branchId: string): BranchMapping {
return {
version: 0,
data: [
{
branchId,
branchMappingLogic: 'true',
},
],
};
}

export function getBranchMapping(branchMappingString: string): BranchMapping {
try {
return JSON.parse(branchMappingString);
} catch {
throw new Error(`Could not parse branchMapping string into a JSON: "${branchMappingString}"`);
}
}

export function getNodesFromStatement(statement: BranchMappingStatement): BranchMappingNode[] {
return statement.slice(1) as BranchMappingNode[];
}
Expand Down Expand Up @@ -73,6 +93,13 @@ export function hashLtOperator(): BranchMappingOperator {
return 'hash_lt';
}

export function assertStatement(node: BranchMappingNode): asserts node is BranchMappingStatement {
assert(
isStatement(node),
'Branch mapping node must be a statement. Received: ' + JSON.stringify(node)
);
}

export function assertNodeObject(node: BranchMappingNode): asserts node is BranchMappingObject {
assert(
isNodeObject(node),
Expand All @@ -83,3 +110,7 @@ export function assertNodeObject(node: BranchMappingNode): asserts node is Branc
export function assertNumber(operand: string | number | string[]): asserts operand is number {
assert(typeof operand === 'number', 'Expected a number. Received: ' + JSON.stringify(operand));
}

export function assertString(operand: string | number | string[]): asserts operand is string {
assert(typeof operand === 'string', 'Expected a string. Received: ' + JSON.stringify(operand));
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { v4 as uuidv4 } from 'uuid';

import {
testChannelObject,
testUpdateBranch1,
testUpdateBranch2,
} from '../../channel/__tests__/fixtures';
import {
BranchMappingOperator,
alwaysTrue,
andStatement,
equalsOperator,
hashLtOperator,
} from '../../channel/branch-mapping';
import { isRollout } from '../utils';
import {
editRolloutBranchMapping,
getRollout,
getRolloutInfoFromBranchMapping,
isConstrainedRollout,
isConstrainedRolloutInfo,
isLegacyRolloutInfo,
isRollout,
} from '../branch-mapping';

const rolloutBranchMapping = {
version: 0,
Expand Down Expand Up @@ -51,6 +64,99 @@ const standardBranchMapping = {
data: [{ branchId: uuidv4(), branchMappingLogic: alwaysTrue() }],
};

describe(isLegacyRolloutInfo, () => {
it('classifies rollouts properly', () => {
const constrainedRollout = getRolloutInfoFromBranchMapping(rolloutBranchMapping);
expect(isLegacyRolloutInfo(constrainedRollout)).toBe(false);
const legacyRollout = getRolloutInfoFromBranchMapping(rolloutBranchMappingLegacy);
expect(isLegacyRolloutInfo(legacyRollout)).toBe(true);
});
});

describe(isConstrainedRollout, () => {
it('classifies rollouts properly', () => {
const constrainedRollout = getRolloutInfoFromBranchMapping(rolloutBranchMapping);
expect(isConstrainedRolloutInfo(constrainedRollout)).toBe(true);
const legacyRollout = getRolloutInfoFromBranchMapping(rolloutBranchMappingLegacy);
expect(isConstrainedRolloutInfo(legacyRollout)).toBe(false);
});
});

describe(getRollout, () => {
it('doesnt get the mapping if it isnt a rollout', () => {
const notRollout = { ...testChannelObject };
notRollout.branchMapping = JSON.stringify(standardBranchMapping);
expect(() => getRollout(notRollout)).toThrowError();
});
it('gets a constrained rollout', () => {
const constrainedRollout = { ...testChannelObject };
const rolloutBranchMappingWithCorrectBranch = { ...rolloutBranchMapping };
rolloutBranchMappingWithCorrectBranch.data[0].branchId = testUpdateBranch1.id;
rolloutBranchMappingWithCorrectBranch.data[1].branchId = testUpdateBranch2.id;
constrainedRollout.branchMapping = JSON.stringify(rolloutBranchMapping);

const rollout = getRollout(constrainedRollout);
expect(rollout.percentRolledOut).toEqual(10);
expect(isConstrainedRolloutInfo(rollout)).toBe(true);
expect(rollout.defaultBranch).toEqual(testUpdateBranch2);
expect(rollout.rolledOutBranch).toEqual(testUpdateBranch1);
expect(rollout.defaultBranchId).toEqual(testUpdateBranch2.id);
expect(rollout.rolledOutBranchId).toEqual(testUpdateBranch1.id);
});
it('gets a legacy rollout', () => {
const rollout = getRollout(testChannelObject);
expect(rollout.percentRolledOut).toEqual(15);
expect(isLegacyRolloutInfo(rollout)).toBe(true);
expect(rollout.defaultBranch).toEqual(testUpdateBranch2);
expect(rollout.rolledOutBranch).toEqual(testUpdateBranch1);
expect(rollout.defaultBranchId).toEqual(testUpdateBranch2.id);
expect(rollout.rolledOutBranchId).toEqual(testUpdateBranch1.id);
});
});

describe(getRolloutInfoFromBranchMapping, () => {
it('doesnt get the mapping if it isnt a rollout', () => {
expect(() => getRolloutInfoFromBranchMapping(standardBranchMapping)).toThrowError();
});
it('gets a constrained rollout', () => {
const rollout = getRolloutInfoFromBranchMapping(rolloutBranchMapping);
expect(rollout.percentRolledOut).toEqual(10);
expect(isConstrainedRolloutInfo(rollout)).toBe(true);
expect(rollout.defaultBranchId).toEqual(rolloutBranchMapping.data[1].branchId);
expect(rollout.rolledOutBranchId).toEqual(rolloutBranchMapping.data[0].branchId);
});
it('gets a legacy rollout', () => {
const rollout = getRolloutInfoFromBranchMapping(rolloutBranchMappingLegacy);
expect(rollout.percentRolledOut).toEqual(10);
expect(isLegacyRolloutInfo(rollout)).toBe(true);
expect(rollout.defaultBranchId).toEqual(rolloutBranchMappingLegacy.data[1].branchId);
expect(rollout.rolledOutBranchId).toEqual(rolloutBranchMappingLegacy.data[0].branchId);
});
});

describe(editRolloutBranchMapping, () => {
it('doesnt edit the branch mapping if it isnt a rollout', () => {
expect(() => editRolloutBranchMapping(standardBranchMapping, 50)).toThrowError();
});
it('doesnt edit the branch mapping if the input is out of range', () => {
expect(() => editRolloutBranchMapping(standardBranchMapping, -1)).toThrowError();
expect(() => editRolloutBranchMapping(standardBranchMapping, 101)).toThrowError();
expect(() => editRolloutBranchMapping(standardBranchMapping, 0.1)).toThrowError();
});
it('edits the branch mapping for a constrained rollout', () => {
const editedBranchMapping = editRolloutBranchMapping(rolloutBranchMapping, 50);
const rollout = getRolloutInfoFromBranchMapping(editedBranchMapping);
expect(rollout.percentRolledOut).toEqual(50);
expect(isConstrainedRolloutInfo(rollout)).toBe(true);
});
it('edits the branch mapping for a legacy rollout', () => {
const editedBranchMapping = editRolloutBranchMapping(rolloutBranchMappingLegacy, 50);
const rollout = getRolloutInfoFromBranchMapping(editedBranchMapping);
expect(rollout.percentRolledOut).toEqual(50);
expect(isLegacyRolloutInfo(rollout)).toBe(true);
});
});

describe(isRollout, () => {
it('detects a rollout made by the cli', () => {
expect(isRollout(rolloutBranchMappingLegacy)).toBe(true);
Expand Down
Loading

0 comments on commit 05799ab

Please sign in to comment.