Skip to content

Commit ce5b297

Browse files
committed
commit
1 parent eabfd9a commit ce5b297

File tree

12 files changed

+7698
-4636
lines changed

12 files changed

+7698
-4636
lines changed

README.md

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,44 @@
22
<a href="https://github.com/actions/typescript-action/actions"><img alt="typescript-action status" src="https://github.com/actions/typescript-action/workflows/build-test/badge.svg"></a>
33
</p>
44

5-
# Create a JavaScript Action using TypeScript
5+
# Cancel Currents run action
66

7-
Use this template to bootstrap the creation of a TypeScript action.:rocket:
7+
This action cancels the current cypress run by calling the Currents API.
88

9-
This template includes compilation support, tests, a validation workflow, publishing, and versioning guidance.
9+
## Inputs
1010

11-
If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action)
11+
### `currents-api-url`
1212

13-
## Create an action from this template
13+
Currents API URL. Default value is `https://api.currents.dev/api/v1`
1414

15-
Click the `Use this Template` and provide the new repo details for your action
15+
### `bearer-token`
1616

17-
## Code in Main
17+
**Required** Bearer authorization token.
18+
19+
### `github-run-id`
20+
21+
**Required** GitHub run id.
22+
23+
### `github-run-attempt`
24+
25+
**Required** GitHub run attempt.
26+
27+
## Example usage
28+
29+
```yaml
30+
- name: Cancel the run if workflow is cancelled
31+
if: ${{ cancelled() }}
32+
uses: currents-dev/cancel-run-action@v1
33+
with:
34+
bearer-token: ${{ secrets.CURRENTS_API_TOKEN }}
35+
github-run-id: ${{ github.run_id }}
36+
github-run-attempt: ${{ github.run_attempt }}
37+
38+
```
39+
40+
## Development
41+
42+
The repository is made using [this](https://github.com/actions/typescript-action) template
1843

1944
> First, you'll need to have a reasonably modern version of `node` handy. This won't work with versions older than 9, for instance.
2045
@@ -40,15 +65,15 @@ $ npm test
4065
...
4166
```
4267

43-
## Change action.yml
68+
### Change action.yml
4469

4570
The action.yml defines the inputs and output for your action.
4671

4772
Update the action.yml with your name, description, inputs and outputs for your action.
4873

4974
See the [documentation](https://help.github.com/en/articles/metadata-syntax-for-github-actions)
5075

51-
## Change the Code
76+
### Change the Code
5277

5378
Most toolkit and CI/CD operations involve async operations so the action is run in an async function.
5479

@@ -88,7 +113,7 @@ Your action is now published! :rocket:
88113

89114
See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
90115

91-
## Validate
116+
### Validate
92117

93118
You can now validate the action by referencing `./` in a workflow in your repo (see [test.yml](.github/workflows/test.yml))
94119

@@ -100,6 +125,6 @@ with:
100125
101126
See the [actions tab](https://github.com/actions/typescript-action/actions) for runs of this action! :rocket:
102127
103-
## Usage:
128+
### Usage:
104129
105130
After testing you can [create a v1 tag](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) to reference the stable and latest V1 action

__tests__/main.test.ts

Lines changed: 164 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,168 @@
1-
import {wait} from '../src/wait'
2-
import * as process from 'process'
3-
import * as cp from 'child_process'
4-
import * as path from 'path'
5-
import {expect, test} from '@jest/globals'
6-
7-
test('throws invalid number', async () => {
8-
const input = parseInt('foo', 10)
9-
await expect(wait(input)).rejects.toThrow('milliseconds not a number')
10-
})
1+
import {run, request} from '../src/main'
2+
import * as core from '@actions/core'
3+
import nock from 'nock'
4+
5+
const currentsApiUrl = 'http://localhost:4000/v1'
6+
const currentsApiCancelationPath = '/runs/cancel-by-github-ci'
7+
const githubRunId = '45166321'
8+
const githubRunAttempt = '1'
9+
10+
describe('input validation', () => {
11+
test('currents-api-url is required', async () => {
12+
const spy = jest.spyOn(core, 'setFailed')
13+
14+
await run()
15+
16+
expect(spy).toHaveBeenCalledWith(
17+
'Input required and not supplied: currents-api-url'
18+
)
19+
})
20+
21+
test('bearer-token is required', async () => {
22+
process.env['INPUT_CURRENTS-API-URL'] = currentsApiUrl
23+
24+
const spy = jest.spyOn(core, 'setFailed')
25+
26+
await run()
27+
28+
expect(spy).toHaveBeenCalledWith(
29+
'Input required and not supplied: bearer-token'
30+
)
31+
})
1132

12-
test('wait 500 ms', async () => {
13-
const start = new Date()
14-
await wait(500)
15-
const end = new Date()
16-
var delta = Math.abs(end.getTime() - start.getTime())
17-
expect(delta).toBeGreaterThan(450)
33+
test('github-run-id is required', async () => {
34+
process.env['INPUT_CURRENTS-API-URL'] = currentsApiUrl
35+
process.env['INPUT_BEARER-TOKEN'] = 'bearer-token'
36+
37+
const spy = jest.spyOn(core, 'setFailed')
38+
39+
await run()
40+
41+
expect(spy).toHaveBeenCalledWith(
42+
'Input required and not supplied: github-run-id'
43+
)
44+
})
45+
46+
test('github-run-attempt is required', async () => {
47+
process.env['INPUT_CURRENTS-API-URL'] = currentsApiUrl
48+
process.env['INPUT_BEARER-TOKEN'] = 'bearer-token'
49+
process.env['INPUT_GITHUB-RUN-ID'] = githubRunId
50+
51+
const spy = jest.spyOn(core, 'setFailed')
52+
53+
await run()
54+
55+
expect(spy).toHaveBeenCalledWith(
56+
'Input required and not supplied: github-run-attempt'
57+
)
58+
})
1859
})
1960

20-
// shows how the runner will run a javascript action with env / stdout protocol
21-
test('test runs', () => {
22-
process.env['INPUT_MILLISECONDS'] = '500'
23-
const np = process.execPath
24-
const ip = path.join(__dirname, '..', 'lib', 'main.js')
25-
const options: cp.ExecFileSyncOptions = {
26-
env: process.env
27-
}
28-
console.log(cp.execFileSync(np, [ip], options).toString())
61+
describe('api request', () => {
62+
beforeEach(() => {
63+
process.env['INPUT_CURRENTS-API-URL'] = currentsApiUrl
64+
process.env['INPUT_BEARER-TOKEN'] = 'bearer-token'
65+
process.env['INPUT_GITHUB-RUN-ID'] = githubRunId
66+
process.env['INPUT_GITHUB-RUN-ATTEMPT'] = githubRunAttempt
67+
})
68+
69+
afterEach(() => {
70+
delete process.env['INPUT_CURRENTS-API-URL']
71+
delete process.env['INPUT_BEARER-TOKEN']
72+
delete process.env['INPUT_GITHUB-RUN-ID']
73+
delete process.env['INPUT_GITHUB-RUN-ATTEMPT']
74+
})
75+
76+
test('should resolve when status code is not 200', () => {
77+
const error = JSON.stringify({
78+
error: 'Invalid params'
79+
})
80+
nock(currentsApiUrl).put(currentsApiCancelationPath).reply(400, error)
81+
expect(
82+
request({
83+
url: `${currentsApiUrl}${currentsApiCancelationPath}`,
84+
body: {
85+
githubRunId,
86+
githubRunAttempt
87+
},
88+
bearerToken: 'token'
89+
})
90+
).rejects.toThrowError(error)
91+
})
92+
93+
test('should fail when status code is 404', async () => {
94+
nock(currentsApiUrl).put(currentsApiCancelationPath).reply(404, {})
95+
const spy = jest.spyOn(core, 'setFailed')
96+
97+
await run()
98+
expect(spy).toHaveBeenCalledWith('Resource not found')
99+
})
100+
101+
test('should retry when status code is 500', async () => {
102+
nock(currentsApiUrl).put(currentsApiCancelationPath).reply(500)
103+
const spy = jest.spyOn(core, 'setFailed')
104+
105+
await run()
106+
expect(spy).toBeCalled()
107+
}, 15000)
108+
109+
test('should fail when the input is invalid', async () => {
110+
process.env['INPUT_CURRENTS-API-URL'] = 'bad url'
111+
const spy = jest.spyOn(core, 'setFailed')
112+
113+
await run()
114+
expect(spy).toHaveBeenCalledWith(expect.any(String))
115+
})
116+
117+
test('should return the result when status code is 200', () => {
118+
const result = {
119+
githubRunId,
120+
githubRunAttempt,
121+
status: 'OK',
122+
actor: 'api',
123+
canceledAt: new Date().toDateString(),
124+
reason: 'api call'
125+
}
126+
127+
nock(currentsApiUrl).put(currentsApiCancelationPath).reply(200, result)
128+
129+
expect(
130+
request({
131+
url: `${currentsApiUrl}${currentsApiCancelationPath}`,
132+
body: {
133+
githubRunId,
134+
githubRunAttempt
135+
},
136+
bearerToken: 'token'
137+
})
138+
).resolves.toEqual({
139+
headers: {
140+
'content-type': 'application/json'
141+
},
142+
result,
143+
statusCode: 200
144+
})
145+
})
146+
147+
test('should show the result when debug is enabled', async () => {
148+
const result = {
149+
githubRunId,
150+
githubRunAttempt,
151+
status: 'OK',
152+
actor: 'api',
153+
canceledAt: new Date().toDateString(),
154+
reason: 'api call'
155+
}
156+
157+
const spy = jest.spyOn(core, 'debug')
158+
159+
// enable debug
160+
process.env['RUNNER_DEBUG'] = '1'
161+
162+
nock(currentsApiUrl).put(currentsApiCancelationPath).reply(200, result)
163+
164+
await run()
165+
166+
expect(spy).toHaveBeenCalled()
167+
})
29168
})

action.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
name: 'Your name here'
2-
description: 'Provide a description here'
3-
author: 'Your name or organization here'
1+
name: "cancel-currents-run"
2+
description: "Cancels Currents run via the API"
43
inputs:
5-
milliseconds: # change this
4+
currents-api-url:
5+
description: "Currents API URL"
6+
required: false
7+
default: "https://api.currents.dev/api/v1"
8+
bearer-token:
9+
description: "Bearer authentication token"
10+
required: true
11+
github-run-id:
12+
description: "GitHub run id"
13+
required: true
14+
github-run-attempt:
15+
description: "GitHub run attempt"
616
required: true
7-
description: 'input description here'
8-
default: 'default value if applicable'
917
runs:
10-
using: 'node16'
11-
main: 'dist/index.js'
18+
using: "node16"
19+
main: "dist/index.js"

babel.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {presets: ['@babel/preset-env']}

0 commit comments

Comments
 (0)