stub more docs, check for errors in issue sync, sort labels by priority and name
This commit is contained in:
parent
b404ecf62e
commit
7bb4e95875
|
@ -42,7 +42,6 @@ const bundle = {
|
|||
},
|
||||
manualChunks(id) {
|
||||
if (id.includes(`${sep}test${sep}`)) {
|
||||
console.log(id, 'belongs to test chunk');
|
||||
return 'test';
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,6 @@ const bundle = {
|
|||
}
|
||||
|
||||
if (testModules.some(mod => id.includes(`${sep}${mod}${sep}`))) {
|
||||
console.log(id, 'belongs to test chunk');
|
||||
return 'test';
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
| Function | Description |
|
||||
| --- | --- |
|
||||
| [resolveLabels(options)](./cautious-journey.resolvelabels.md) | |
|
||||
| [resolveLabels(options)](./cautious-journey.resolvelabels.md) | Resolve the desired set of labels, given a starting set and the flags/states to be applied. |
|
||||
| [syncIssues(options)](./cautious-journey.syncissues.md) | |
|
||||
| [syncLabels(options)](./cautious-journey.synclabels.md) | |
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
## resolveLabels() function
|
||||
|
||||
Resolve the desired set of labels, given a starting set and the flags/states to be applied.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
errors: Array<unknown>;
|
||||
errors: Array<ErrorRecord>;
|
||||
```
|
||||
|
|
|
@ -17,6 +17,6 @@ export interface ResolveResult
|
|||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [changes](./cautious-journey.resolveresult.changes.md) | Array<ChangeRecord> | |
|
||||
| [errors](./cautious-journey.resolveresult.errors.md) | Array<unknown> | |
|
||||
| [errors](./cautious-journey.resolveresult.errors.md) | Array<ErrorRecord> | |
|
||||
| [labels](./cautious-journey.resolveresult.labels.md) | Array<string> | |
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ projects:
|
|||
privateKey: |
|
||||
KEY MATERIAL HERE
|
||||
token: ''
|
||||
type: 'installation'
|
||||
type: 'app'
|
||||
type: 'github'
|
||||
states:
|
||||
- name: scope
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
# Getting Started
|
||||
|
||||
This guide explains how to start using `cautious-journey` to manage project and issue labels.
|
||||
|
||||
## Contents
|
||||
|
||||
- [Getting Started](#getting-started)
|
||||
- [Contents](#contents)
|
||||
- [Setup](#setup)
|
||||
- [Installing](#installing)
|
||||
- [Running](#running)
|
||||
- [Configuring](#configuring)
|
||||
- [Labels](#labels)
|
||||
- [Flag Labels](#flag-labels)
|
||||
- [State Labels](#state-labels)
|
||||
- [Projects](#projects)
|
||||
- [Configuring Multiple Projects](#configuring-multiple-projects)
|
||||
- [Running Select Projects](#running-select-projects)
|
||||
- [Remotes](#remotes)
|
||||
- [Copying Project Remotes](#copying-project-remotes)
|
||||
- [Commands](#commands)
|
||||
- [Sync Labels](#sync-labels)
|
||||
- [Sync Issues](#sync-issues)
|
||||
- [Transitions](#transitions)
|
||||
- [Flag Transitions](#flag-transitions)
|
||||
- [State Transitions](#state-transitions)
|
||||
|
||||
## Setup
|
||||
|
||||
### Installing
|
||||
|
||||
TODO: how would you install the app?
|
||||
|
||||
### Running
|
||||
|
||||
TODO: how would you run the app?
|
||||
|
||||
### Configuring
|
||||
|
||||
TODO: how would you configure the app?
|
||||
|
||||
## Labels
|
||||
|
||||
TODO: what are labels? what kinds of labels do we support?
|
||||
|
||||
### Flag Labels
|
||||
|
||||
TODO: what are flag labels?
|
||||
|
||||
### State Labels
|
||||
|
||||
TODO: what are state labels?
|
||||
|
||||
## Projects
|
||||
|
||||
TODO: what are projects? how are they managed? how do you pick which projects to run?
|
||||
|
||||
### Configuring Multiple Projects
|
||||
|
||||
TODO: how would you configure the app to run for multiple projects?
|
||||
|
||||
### Running Select Projects
|
||||
|
||||
TODO: how would you run a single project, or a subset?
|
||||
|
||||
## Remotes
|
||||
|
||||
TODO: what are remotes? how are they configured?
|
||||
|
||||
### Copying Project Remotes
|
||||
|
||||
TODO: how would you share a remote config block between two projects?
|
||||
|
||||
## Commands
|
||||
|
||||
TODO: what commands are present?
|
||||
|
||||
### Sync Labels
|
||||
|
||||
TODO: what happens when you sync the project labels?
|
||||
|
||||
### Sync Issues
|
||||
|
||||
TODO: what happens when you sync the issue labels?
|
||||
|
||||
## Transitions
|
||||
|
||||
### Flag Transitions
|
||||
|
||||
TODO: how are flag labels added and removed?
|
||||
|
||||
### State Transitions
|
||||
|
||||
TODO: how are state labels added and removed?
|
|
@ -95,3 +95,21 @@ export function splitName(name: string): Array<string> {
|
|||
export function valueName(state: StateLabel, value: StateValue): string {
|
||||
return `${state.name}/${value.name}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort labels by their priority field, highest first.
|
||||
*
|
||||
* TODO: add some sort options: high-first or low-first, case-sensitivity
|
||||
*/
|
||||
export function prioritizeLabels<TLabel extends BaseLabel>(labels: Array<TLabel>): Array<TLabel> {
|
||||
return labels.sort((a, b) => {
|
||||
if (a.priority === b.priority) {
|
||||
const aName = a.name.toLocaleLowerCase();
|
||||
const bName = b.name.toLocaleLowerCase();
|
||||
return aName.localeCompare(bName);
|
||||
} else {
|
||||
// B first for high-to-low
|
||||
return b.priority - a.priority;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { FlagLabel, StateLabel, valueName } from './labels';
|
||||
import { FlagLabel, prioritizeLabels, StateLabel, valueName } from './labels';
|
||||
|
||||
/**
|
||||
* How a label changed.
|
||||
*/
|
||||
export enum ChangeEffect {
|
||||
export enum ChangeVerb {
|
||||
EXISTING = 'existing',
|
||||
CREATED = 'created',
|
||||
REMOVED = 'removed',
|
||||
|
@ -14,8 +14,24 @@ export enum ChangeEffect {
|
|||
* Details of a label change.
|
||||
*/
|
||||
export interface ChangeRecord {
|
||||
/**
|
||||
* The label which caused this change.
|
||||
*/
|
||||
cause: string;
|
||||
effect: ChangeEffect;
|
||||
|
||||
/**
|
||||
* How the label was changed.
|
||||
*/
|
||||
effect: ChangeVerb;
|
||||
|
||||
/**
|
||||
* The label being changed.
|
||||
*/
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface ErrorRecord {
|
||||
error: Error;
|
||||
label: string;
|
||||
}
|
||||
|
||||
|
@ -33,16 +49,20 @@ export interface ResolveInput {
|
|||
*/
|
||||
export interface ResolveResult {
|
||||
changes: Array<ChangeRecord>;
|
||||
errors: Array<unknown>;
|
||||
errors: Array<ErrorRecord>;
|
||||
labels: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the desired set of labels, given a starting set and the flags/states to be
|
||||
* applied.
|
||||
*/
|
||||
export function resolveLabels(options: ResolveInput): ResolveResult {
|
||||
const activeLabels = new Set(options.labels);
|
||||
const changes: Array<ChangeRecord> = [];
|
||||
const errors: Array<unknown> = [];
|
||||
const errors: Array<ErrorRecord> = [];
|
||||
|
||||
const sortedFlags = options.flags.sort((a, b) => a.priority - b.priority);
|
||||
const sortedFlags = prioritizeLabels(options.flags);
|
||||
for (const flag of sortedFlags) {
|
||||
const { name } = flag;
|
||||
if (activeLabels.has(name)) {
|
||||
|
@ -51,11 +71,13 @@ export function resolveLabels(options: ResolveInput): ResolveResult {
|
|||
}
|
||||
}
|
||||
|
||||
const sortedStates = options.states.sort((a, b) => a.priority - b.priority);
|
||||
const sortedStates = prioritizeLabels(options.states);
|
||||
for (const state of sortedStates) {
|
||||
for (const value of state.values) {
|
||||
const sortedValues = prioritizeLabels(state.values);
|
||||
for (const value of sortedValues) {
|
||||
const name = valueName(state, value);
|
||||
if (activeLabels.has(name)) {
|
||||
// TODO: check higher-priority values
|
||||
// TODO: check removes
|
||||
// TODO: check requires
|
||||
// TODO: check becomes
|
||||
|
|
|
@ -29,7 +29,7 @@ export async function syncIssues(options: SyncOptions): Promise<unknown> {
|
|||
});
|
||||
|
||||
// TODO: prompt user to update this particular issue
|
||||
if (resolution.changes.length > 0) {
|
||||
if (resolution.changes.length > 0 && resolution.errors.length === 0) {
|
||||
options.logger.info({ issue, resolution }, 'updating issue');
|
||||
await options.remote.updateIssue({
|
||||
...issue,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { expect } from 'chai';
|
||||
|
||||
import { getLabelNames } from '../src/labels';
|
||||
import { getLabelNames, prioritizeLabels } from '../src/labels';
|
||||
|
||||
describe('labels', () => {
|
||||
describe('label helpers', () => {
|
||||
describe('label name helper', () => {
|
||||
it('should return an empty set', () => {
|
||||
expect(getLabelNames([], []).size).to.equal(0);
|
||||
|
@ -58,4 +58,38 @@ describe('labels', () => {
|
|||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prioritize labels helper', () => {
|
||||
it('should sort by priority', () => {
|
||||
const HIGH_LABEL = {
|
||||
name: 'high',
|
||||
priority: 5,
|
||||
requires: [],
|
||||
};
|
||||
const LOW_LABEL = {
|
||||
name: 'low',
|
||||
priority: 1,
|
||||
requires: [],
|
||||
};
|
||||
|
||||
const sorted = prioritizeLabels([LOW_LABEL, HIGH_LABEL]);
|
||||
expect(sorted[0]).to.deep.equal(HIGH_LABEL);
|
||||
});
|
||||
|
||||
it('should sort by name when priority is equal', () => {
|
||||
const FIRST_LABEL = {
|
||||
name: 'label-a',
|
||||
priority: 1,
|
||||
requires: [],
|
||||
};
|
||||
const SECOND_LABEL = {
|
||||
name: 'label-b',
|
||||
priority: 1,
|
||||
requires: [],
|
||||
};
|
||||
|
||||
const sorted = prioritizeLabels([SECOND_LABEL, FIRST_LABEL]);
|
||||
expect(sorted[0]).to.deep.equal(FIRST_LABEL);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,8 +3,30 @@ import { expect } from 'chai';
|
|||
import { resolveLabels } from '../src/resolve';
|
||||
import { TEST_CASES } from './resolve/cases';
|
||||
|
||||
const TEST_LABELS = ['foo', 'bar'];
|
||||
|
||||
describe('resolve labels', () => {
|
||||
it('should return the existing labels when no rules are provided');
|
||||
describe('with empty rule set', () => {
|
||||
it('should return the existing labels', () => {
|
||||
const result = resolveLabels({
|
||||
flags: [],
|
||||
labels: TEST_LABELS,
|
||||
states: [],
|
||||
});
|
||||
|
||||
expect(result.labels).to.deep.equal(TEST_LABELS);
|
||||
});
|
||||
|
||||
it('should not make any changes', () => {
|
||||
const result = resolveLabels({
|
||||
flags: [],
|
||||
labels: TEST_LABELS,
|
||||
states: [],
|
||||
});
|
||||
|
||||
expect(result.changes.length).to.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
// procedural tests
|
||||
describe('resolver test cases', () => {
|
||||
|
|
Loading…
Reference in New Issue