Add a new boolean parameter to action `delete-only-untagged-versions`. When true, only versions that do not have any tags will be deleted.
486 lines
13 KiB
TypeScript
486 lines
13 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
import {rest} from 'msw'
|
|
import {setupServer} from 'msw/node'
|
|
import {Input, InputParams} from '../src/input'
|
|
import {deleteVersions, finalIds, RATE_LIMIT} from '../src/delete'
|
|
import {getMockedVersionsResponse} from './version/rest.mock'
|
|
import {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods/dist-types/generated/parameters-and-response-types'
|
|
|
|
type GetVersionsResponseData =
|
|
RestEndpointMethodTypes['packages']['getAllPackageVersionsForPackageOwnedByUser']['response']['data']
|
|
|
|
describe('index tests -- call rest', () => {
|
|
let server = setupServer()
|
|
|
|
beforeEach(() => {
|
|
server = setupServer()
|
|
server.listen()
|
|
})
|
|
|
|
afterEach(() => {
|
|
server.close()
|
|
})
|
|
|
|
it('finalIds test - supplied package version id', done => {
|
|
const suppliedIds = ['123', '456', '789']
|
|
finalIds(getInput({packageVersionIds: suppliedIds})).subscribe(ids => {
|
|
expect(ids).toStrictEqual(suppliedIds)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIDs test - success', done => {
|
|
const numVersions = 10
|
|
let apiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
finalIds(getInput()).subscribe(ids => {
|
|
expect(apiCalled).toBe(1)
|
|
expect(ids.length).toBe(numVersions)
|
|
for (let i = 0; i < numVersions; i++) {
|
|
expect(ids[i]).toBe(versions[i].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIDs test - success - GHES', done => {
|
|
process.env.GITHUB_API_URL = 'https://github.someghesinstance.com/api/v3'
|
|
|
|
const numVersions = 10
|
|
let apiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://github.someghesinstance.com/api/v3/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
finalIds(getInput()).subscribe(ids => {
|
|
expect(apiCalled).toBe(1)
|
|
expect(ids.length).toBe(numVersions)
|
|
for (let i = 0; i < numVersions; i++) {
|
|
expect(ids[i]).toBe(versions[i].id.toString())
|
|
}
|
|
|
|
delete process.env.GITHUB_API_URL
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIDs test - success - pagination', done => {
|
|
const numVersions = RATE_LIMIT * 2
|
|
let apiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
|
|
const firstPage = versions.slice(0, RATE_LIMIT)
|
|
const secondPage = versions.slice(RATE_LIMIT)
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
const page = req.url.searchParams.get('page')
|
|
if (page === '1') {
|
|
return res(ctx.status(200), ctx.json(firstPage))
|
|
} else if (page === '2') {
|
|
return res(ctx.status(200), ctx.json(secondPage))
|
|
} else {
|
|
return res(ctx.status(200), ctx.json([]))
|
|
}
|
|
}
|
|
)
|
|
)
|
|
|
|
finalIds(getInput()).subscribe(ids => {
|
|
expect(apiCalled).toBe(3) // 2 full pages + 1 empty page
|
|
// never returns more than RATE_LIMIT versions
|
|
expect(ids.length).toBe(RATE_LIMIT)
|
|
for (let i = 0; i < RATE_LIMIT; i++) {
|
|
expect(ids[i]).toBe(versions[i].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIDs test - success - sorting accross pages', done => {
|
|
const numVersions = RATE_LIMIT * 2
|
|
let apiCalled = 0
|
|
|
|
// versions is in ascending order of created_at
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
|
|
// return newer versions on first page to test sorting
|
|
const firstPage = versions.slice(RATE_LIMIT).reverse()
|
|
const secondPage = versions.slice(0, RATE_LIMIT).reverse()
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
const page = req.url.searchParams.get('page')
|
|
if (page === '1') {
|
|
return res(ctx.status(200), ctx.json(firstPage))
|
|
} else if (page === '2') {
|
|
return res(ctx.status(200), ctx.json(secondPage))
|
|
} else {
|
|
return res(ctx.status(200), ctx.json([]))
|
|
}
|
|
}
|
|
)
|
|
)
|
|
|
|
finalIds(getInput()).subscribe(ids => {
|
|
expect(apiCalled).toBe(3) // 2 full pages + 1 empty page
|
|
expect(ids.length).toBe(RATE_LIMIT)
|
|
for (let i = 0; i < RATE_LIMIT; i++) {
|
|
expect(ids[i]).toBe(versions[i].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIds test - do not delete more than numOldVersionsToDelete', done => {
|
|
const numVersions = 50
|
|
let apiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
const numOldVersionsToDelete = 10
|
|
|
|
finalIds(getInput({numOldVersionsToDelete})).subscribe(ids => {
|
|
expect(apiCalled).toBe(1)
|
|
expect(ids.length).toBe(numOldVersionsToDelete)
|
|
for (let i = 0; i < numOldVersionsToDelete; i++) {
|
|
expect(ids[i]).toBe(versions[i].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIds test - keep minVersionsToKeep', done => {
|
|
const numVersions = 50
|
|
let apiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
const minVersionsToKeep = 10
|
|
|
|
finalIds(getInput({minVersionsToKeep})).subscribe(ids => {
|
|
expect(apiCalled).toBe(1)
|
|
expect(ids.length).toBe(numVersions - minVersionsToKeep)
|
|
for (let i = 0; i < numVersions - minVersionsToKeep; i++) {
|
|
expect(ids[i]).toBe(versions[i].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIds test - delete only prerelease versions with minVersionsToKeep', done => {
|
|
const numVersions = 50
|
|
let apiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
// make half versions prerelease
|
|
for (let i = 0; i < numVersions; i++) {
|
|
if (i % 2 === 0) {
|
|
versions[i].name += '-alpha'
|
|
}
|
|
}
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
const toDelete = numVersions / 2 - 10
|
|
|
|
finalIds(
|
|
getInput({
|
|
ignoreVersions: RegExp('^(0|[1-9]\\d*)((\\.(0|[1-9]\\d*))*)$'),
|
|
minVersionsToKeep: 10
|
|
})
|
|
).subscribe(ids => {
|
|
expect(apiCalled).toBe(1)
|
|
expect(ids.length).toBe(toDelete)
|
|
for (let i = 0; i < toDelete; i++) {
|
|
expect(ids[i]).toBe(versions[i * 2].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIds test - delete only untagged versions with minVersionsToKeep', done => {
|
|
const numVersions = 50
|
|
const numTaggedVersions = 20
|
|
const numUntaggedVersions = numVersions - numTaggedVersions
|
|
|
|
const taggedVersions = getMockedVersionsResponse(
|
|
numTaggedVersions,
|
|
0,
|
|
'container',
|
|
true
|
|
)
|
|
const untaggedVersions = getMockedVersionsResponse(
|
|
numUntaggedVersions,
|
|
numTaggedVersions,
|
|
'container',
|
|
false
|
|
)
|
|
const versions = taggedVersions.concat(untaggedVersions)
|
|
|
|
let apiCalled = 0
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/container/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
finalIds(
|
|
getInput({
|
|
minVersionsToKeep: 10,
|
|
deleteUntaggedVersions: 'true',
|
|
packageType: 'container'
|
|
})
|
|
).subscribe(ids => {
|
|
expect(apiCalled).toBe(1)
|
|
expect(ids.length).toBe(numUntaggedVersions - 10)
|
|
for (let i = 0; i < numUntaggedVersions - 10; i++) {
|
|
expect(ids[i]).toBe(untaggedVersions[i].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('finalIds test - no versions deleted if API error even once', done => {
|
|
const numVersions = RATE_LIMIT * 2
|
|
let apiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
|
|
const firstPage = versions.slice(0, RATE_LIMIT)
|
|
const secondPage = versions.slice(RATE_LIMIT)
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
apiCalled++
|
|
const page = req.url.searchParams.get('page')
|
|
if (page === '1') {
|
|
return res(ctx.status(200), ctx.json(firstPage))
|
|
} else if (page === '2') {
|
|
return res(ctx.status(500), ctx.json([]))
|
|
} else {
|
|
return res(ctx.status(200), ctx.json([]))
|
|
}
|
|
}
|
|
)
|
|
)
|
|
|
|
finalIds(getInput()).subscribe(
|
|
() => {
|
|
done.fail('should not complete')
|
|
},
|
|
err => {
|
|
expect(apiCalled).toBe(2) // 1 full page + 1 error page
|
|
expect(err).toBeTruthy()
|
|
expect(err).toContain('get versions API failed.')
|
|
done()
|
|
}
|
|
)
|
|
})
|
|
|
|
it('deleteVersions test - missing token', done => {
|
|
deleteVersions(getInput({token: ''})).subscribe({
|
|
error: err => {
|
|
expect(err).toBeTruthy()
|
|
done()
|
|
},
|
|
complete: async () => done.fail('no error thrown')
|
|
})
|
|
})
|
|
|
|
it('deleteVersions test - missing packageName', done => {
|
|
deleteVersions(getInput({packageName: ''})).subscribe({
|
|
error: err => {
|
|
expect(err).toBeTruthy()
|
|
done()
|
|
},
|
|
complete: async () => done.fail('no error thrown')
|
|
})
|
|
})
|
|
|
|
it('deleteVersions test - missing packageType', done => {
|
|
deleteVersions(getInput({packageType: ''})).subscribe({
|
|
error: err => {
|
|
expect(err).toBeTruthy()
|
|
done()
|
|
},
|
|
complete: async () => done.fail('no error thrown')
|
|
})
|
|
})
|
|
|
|
it('deleteVersions test - zero numOldVersionsToDelete', done => {
|
|
deleteVersions(getInput({numOldVersionsToDelete: 0})).subscribe(result => {
|
|
expect(result).toBe(true)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('deleteVersions test - success complete flow', done => {
|
|
const numVersions = 10
|
|
let getApiCalled = 0
|
|
let deleteApiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
const versionsDeleted: string[] = []
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
getApiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
server.use(
|
|
rest.delete(
|
|
'https://api.github.com/users/test-owner/packages/npm/test-package/versions/:versionId',
|
|
(req, res, ctx) => {
|
|
deleteApiCalled++
|
|
versionsDeleted.push(req.params.versionId as string)
|
|
return res(ctx.status(204))
|
|
}
|
|
)
|
|
)
|
|
|
|
deleteVersions(getInput())
|
|
.subscribe(result => {
|
|
expect(result).toBe(true)
|
|
})
|
|
.add(() => {
|
|
expect(getApiCalled).toBe(1)
|
|
expect(deleteApiCalled).toBe(numVersions)
|
|
for (let i = 0; i < numVersions; i++) {
|
|
expect(versionsDeleted[i]).toBe(versions[i].id.toString())
|
|
}
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('deleteVersions test - success complete flow - GHES', done => {
|
|
process.env.GITHUB_API_URL = 'https://github.someghesinstance.com/api/v3'
|
|
|
|
const numVersions = 10
|
|
let getApiCalled = 0
|
|
let deleteApiCalled = 0
|
|
|
|
const versions = getMockedVersionsResponse(numVersions)
|
|
const versionsDeleted: string[] = []
|
|
|
|
server.use(
|
|
rest.get(
|
|
'https://github.someghesinstance.com/api/v3/users/test-owner/packages/npm/test-package/versions',
|
|
(req, res, ctx) => {
|
|
getApiCalled++
|
|
return res(ctx.status(200), ctx.json(versions))
|
|
}
|
|
)
|
|
)
|
|
|
|
server.use(
|
|
rest.delete(
|
|
'https://github.someghesinstance.com/api/v3/users/test-owner/packages/npm/test-package/versions/:versionId',
|
|
(req, res, ctx) => {
|
|
deleteApiCalled++
|
|
versionsDeleted.push(req.params.versionId as string)
|
|
return res(ctx.status(204))
|
|
}
|
|
)
|
|
)
|
|
|
|
deleteVersions(getInput())
|
|
.subscribe(result => {
|
|
expect(result).toBe(true)
|
|
})
|
|
.add(() => {
|
|
expect(getApiCalled).toBe(1)
|
|
expect(deleteApiCalled).toBe(numVersions)
|
|
for (let i = 0; i < numVersions; i++) {
|
|
expect(versionsDeleted[i]).toBe(versions[i].id.toString())
|
|
}
|
|
|
|
delete process.env.GITHUB_API_URL
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
const defaultInput: InputParams = {
|
|
packageVersionIds: [],
|
|
owner: 'test-owner',
|
|
packageName: 'test-package',
|
|
packageType: 'npm',
|
|
numOldVersionsToDelete: RATE_LIMIT,
|
|
minVersionsToKeep: -1,
|
|
ignoreVersions: RegExp('^$'),
|
|
token: 'test-token'
|
|
}
|
|
|
|
function getInput(params?: InputParams): Input {
|
|
return new Input({...defaultInput, ...params})
|
|
}
|