Configuration in package.json with oclif property

"oclif": {
  "commands": "./lib/commands",
  "bin": "my-oclif-cli",
  "plugins": [
    "@oclif/plugin-help"
  ],
  "hooks": {
    "commit": "./lib/hooks/commit/commit"
  }
},

oclif CLI manifest command generates configuration declaration for publish and load details purposes

List of useful plugins made by oclif, like plugin-help, plugin-autocomplete or plugin-plugins

Hooks

Extending commands like lifecycle callbacks

Custom hooks can be called programmatically

await this.config.runHook('custom', { arguments })

1. Generate a hook to notify slack on issues update

oclif hook notify --event=notify
cat src/hooks/notify/notify.ts
import {Hook} from '@oclif/config'

const hook: Hook<'notify'> = async function (opts) {
  process.stdout.write(`example hook running ${opts.id}\n`)
}

export default hook

2. Let's modify github:assignee command so it sends a notification to slack

my-oclif-cli github:assignee
## after the issue start command is finished
## the notify hook sends slack message

3. We'll need to add a environment variable input flag in the same way we did with slack command itself

slackWebhookUrl: flags.string({
  env: 'SLACK_WEBHOOK_URL',
  required: true
})

4. Parse the flag inside the github:assignee command

const {slackWebhookUrl: url} = flags

5. To execute the hook call the runHook() method on a command's context with appropriate arguments

this.config.runHook('notify', {url, text})

Now oclif should be able to find existing notify functionality

spoiler alert

Notify slack on assignee change code

Add a test to check the output of the github:issues

npm test

> my-oclif@1.0.0 test /Users/paulcodiny/Projects/clits/experiments/my-oclif-cli
> nyc --extension .ts mocha --forbid-only "test/commands/github/issues.test.ts"



  github:issues
...

Getting a list of issues... done
Number Title                              Assignee State Link                                                 
33272  Google feedback on TypeScript 3.5  evmar    open  /microsoft/TypeScript/issues/33272 
    ✓ should format the table (3305ms)


  1 passing (3s)
...

Update the package.json

Basically, for now we can focus only on one test and for it let's update a bit the package.json

{
  "scripts": {
    "test": "nyc --extension .ts mocha --forbid-only \"test/commands/github/issues.test.ts\"",
  }
}

Write the test

1. Import required dependencies

import {expect, test} from '@oclif/test'

2. Create a describe section for the command

describe('github:issues', () => {
  // ...
})

3. Create a test for the issues command

test
  // ... 

4. Mock the response from github with the help of nock package. Please note, we don't have data property in the response. If's automatically created for us by nock

test
  .nock('https://api.github.com', api => api
    .get('/repos/korzio/note/issues')
    .reply(200, [
      {
        number: '33272',
        title: 'Google feedback on TypeScript 3.5 ',
        assignee: {
          login: 'evmar'
        },
        state: 'open',
        html_url: 'https://github.com/microsoft/TypeScript/issues/33272'
      }
    ])
  )

5. Capture the stdout to the variable. Pass { print: true } to simplify debugging. It's not required for your build pipelines (CI/CD) and can be even harmful for your logs

test
  // nock...
  .stdout({ print: true })

6. Next let's run the command. We don't need to provide arguments - for now it will be korzio/note

test
  // nock...
  // stdout...
  .command(['github:issues'])

7. After all it's time for the expectations - oclif uses chai as the expectation library underneath

test
  // .nock...
  // .stdout...
  // .command...
  .it('should show the issues from github', ctx => {
     expect(ctx.stdout)
       .to.contain('33272')
       .and.to.contain('Google feedback on TypeScript 3.5')
       .and.to.contain('evmar')
       .and.to.contain('open')
       .and.to.contain('https://github.com/microsoft/TypeScript/issues/33272')
   })

spoiler alert

github:issues test

1. Move Github commands and logic into a new plugin

oclif plugin manage-github

     _-----_
    |       |    ╭──────────────────────────╮
    |--(o)--|    │   Time to build a oclif  │
   `---------´   │  plugin! Version: 1.13.6 │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? npm package name manage-github
? description
? author Alex Korzhikov @korzio
? version 0.0.0
? license MIT
? Select a package manager npm
? TypeScript Yes
? Use tslint (linter for TypeScript) Yes
? Use mocha (testing framework) Yes

2. Move all the github related project code into a generated plugin

3. Update CLI core to be able installing other plugins

Please note - if in the first oclif exercise the CLI was generated as multi, package.json should already contain this dependency

npm i @oclif/plugin-plugins

4. Test functionality locally by installing the plugin into a core

my-oclif-cli plugins:link ./manage-github
my-oclif-cli github:assignee
# should still work

spoiler alert

Split project code into plugins