An open API service indexing awesome lists of open source software.

https://github.com/financial-times/nori

🍙 exploratory command-line tool to make changes across multiple repositories & track their progress
https://github.com/financial-times/nori

cli command-line-tool customer-products enquirer interactive migrations platforms-customer-products

Last synced: 11 months ago
JSON representation

🍙 exploratory command-line tool to make changes across multiple repositories & track their progress

Awesome Lists containing this project

README

          


nori


npm


CircleCI

_exploratory command-line tool to make changes across multiple repositories & track their progress_

words defined by this readme are written in bold

Nori is a command-line application for managing changes across multiple (usually Github) repositories. It allows you to build up a sequence of [**Operations**](#operations) to go through the process of discovering repositories to change, cloning them & making the changes, creating Pull Requests for the changes, and tracking the progress of the Pull Requests in a Github Project. The main interface for Nori is an interactive command-line wizard, which prompts you for which operations to run, and the arguments needed for each operation.


nori screencast

## Usage

```sh
npx nori
```

This temporarily installs Nori and runs the interactive wizard. The first time you run it, it will prompt you for various configuration variables, which are required only for certain operations. It'll then ask you to `Create a session`. Give the session a memorable name. The wizard takes you through the operations you can run. At any point you can exit by pressing Ctrl+C or selecting `Done`. Your progress is saved under the name you gave when you started `nori`. Next time you run it, it will display a list of previous sessions that you can resume, most recent last.

If you'll be running `nori` frequently, install it globally:

```sh
npm install -g nori
```

`nori` can run operations via the interactive prompt, or directly on the command line. Operations **output** a particular type of data, and some operations have one or more **inputs**, which are types of data that must be gathered before you can run the operation. The interactive prompt will only enable the operations you have the data for so far. When running from the command line, you can pass this data around by [**Piping**](#piping) the operations, or by using a [**State File**](#state-file).

Run `nori` with the name of the operation, and any arguments it requires as double-dashed command line arguments (`nori` understands `--kebab-case` arguments and transforms them to `camelCase`). If you're running in an interactive shell, `nori` will prompt for any missing arguments.

For example, to consume repositories from `repos.txt` and output the formatted list:

```sh
⟩ nori file --file repos.txt
https://github.com/financial-times-sandbox/Abandoned-Toothbrush
https://github.com/financial-times-sandbox/Western-Storm
```

Every operation supports the `--json` flag, which outputs all data found formatted as JSON:

```sh
⟩ nori file --file repos.txt --json
[
{
"owner": "financial-times-sandbox",
"name": "Abandoned-Toothbrush"
},
{
"owner": "financial-times-sandbox",
"name": "Western-Storm"
}
]
```

## Operations

### File

##### `nori file --file `

Get a list of repositories from a text file, structured as line-separated `owner/name` strings (optionally with leading `https://github.com/`).


Arguments
file
path to the text file to read, relative to the current working directory


Inputs
none


Output
repos

### Get repositories through Bizops
Before executing any of the two commands below, either through `npx nori` interactive mode, or directly through the command line, make sure you set the env variable `BIZ_OPS_API_KEY`. To get the key, request a key with a Biz Ops API policy from https://apigateway.in.ft.com/key-form/developer.

##### `nori team-repos`
This operation gets all the repositories from the team you have selected.
It shows a list of teams in customer products (obtained from Bizops) which you can select.


Arguments
None
Teams to be selected when command is run


Inputs
none


Output
repos

##### `nori graphql-repos --file `
This operation gets repositories by executing the file that you pass in containing your own graphql query.


Arguments
file
path to a .graphql | .txt file containing graphql query for repositories


Inputs
none


Output
repos

### Filter repository name

##### `nori filter-repo-name --filter `

Filter the list of repositories by their names.


Arguments
filter
regular expression to filter the names of the repos by


Inputs
repos


Output
repos

### Clone

##### `nori clone`

Clone each of the list of repositories


Arguments
none


Inputs
repos


Output
clones

### Run Script

##### `nori run-script --script --branch `

Create a branch and run a script on it. If the provided branch name already exists, Nori will append a number to it (e.g. `branch` → `branch-1`).


Arguments
script
path to the script to run, relative to the current working directory. should have executable permissions


branch
name of the branch to create


Inputs
clones


Output
localBranches

The script has the responsibility to:

- Make changes to the files in a local clone of a git repository
- Add those changes to git
- Commit those changes to git

Nori will take care of creating branches. The main benefit
of this approach is that scripts do not _need_
`nori` for you to be able to run them. This makes development,
debugging and one-off runs of a script much simpler.

### Push Branches

##### `nori push-branches`

Push each repository's local branch to the remote. If a branch already exists on the remote with the same name as the local branch, Nori will append a number to it (e.g. `branch` → `branch-1`).


Arguments
none


Inputs
clones, localBranches


Output
remoteBranches

### Pull Requests
If you are planning to raise PRs, please add your github personal access token to the githubAccessToken object in `~/.config/nori-workspace/config.json`. Authenticating increases the [secondary rate limit](https://docs.github.com/en/rest/guides/best-practices-for-integrators#dealing-with-secondary-rate-limits) of GitHub API, which increases your chance to raise multiple PRs without being blocked by the limit.

##### `nori prs --templates.title --templates.body `

Create a Pull Request for each of the pushed branches.


Arguments
templates.title
the title of the pull requests. you can use Javascript ${} template string syntax. available variables are repo.owner, repo.name and branch.


templates.body
the body of the pull requests. supports templates like title


Configuration
githubAccessToken

Github personal access token with repo scope



Inputs
repos, branches


Output
prs

### Create Project

##### `nori create-project --project-data.name --project-data.org `

Create a Github Project.


Arguments
projectData.name
the name of the project to create


projectData.org
the org to create the project in. this must be the same org as every repo that you've created a PR on.


Configuration
githubAccessToken

Github personal access token with repo scope



Inputs
none


Output
project

**NB** _we're considering what to do about repos from multiple orgs, see [#62](https://github.com/Financial-Times/nori/issue/62)_

**NB** _the project will have `To Do`, `In Progress` and `Done` columns, but there's currently no way to set up automatic transitions using the Github API. you'll have to set that up manually if you want the project board to reflect the state of the PRs_

### Get Project

##### `nori get-project --project-url `

Get a project from Github.


Arguments
projectUrl
URL of the Github project page


Configuration
githubAccessToken

Github personal access token with repo scope



Inputs
none


Output
project

### Add to Project

##### `nori add-to-project`

Add the [PRs](#pull-requests) to the project.


Arguments
noned


Configuration
githubAccessToken

Github personal access token with repo scope



Inputs
prs, project


Output
cards

## State Files

When running the interactive prompt, your progress is automatically saved to a state file. It contains the list of operations you've run & the arguments given to them, and a cache of the data returned by the operations.

State files are kept in the folder `~/.config/nori-workspace` (this is also where repositories are cloned to). When you start the interactive prompt, it will list any state files already in the workspace folder, allowing you to resume previous sessions.

Individual operations can also read and save to state files with the `--state-file path/to/file.json` option. When you run an operation with a path to a state file that doesn't exist, it will ask if you want to create it. When the operation completes, it'll have added itself and the data it returned to the state file.

The `--state-file` option can also be used with the interactive prompt, which will skip the step asking you to create a state file or use one from the `nori` workspace folder, and allow you to use a state file from any location. State files are compatible between individual operations and the interactive prompt, which lets you shuffle between the two modes.

## Piping

State can also be passed between operations using shell pipes. This is equivalent to running them in sequence and reusing the same state file.

```sh
nori file --file repos.txt | nori run-script --script script.sh --branch change
```

Note that interactive features, such as prompting for missing arguments, won't be available when piping. If any arguments are missing, the operation will error instead. The same goes for providing a state file via the command line argument; it's an error to use `--state-file` and pipe as well. To load or save a state file in a piped operation, use [shell redirection](https://www.tldp.org/LDP/abs/html/io-redirection.html):

```sh
nori file --file repos.txt < input-state.json | nori run-script --script script.sh --branch change > output-state.json
# └─────────┬────────┘ └─────────┬─────────┘
# read input from input-state.json write output to output-state.json
```

## Licence

MIT. © 2019 Financial Times. Made with :green_heart: by FT.com Enabling Technologies Group