Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a31a43afa6 | ||
|
|
56849b848a | ||
|
|
000223ef3e | ||
|
|
df897cea27 | ||
|
|
b77daeff53 | ||
|
|
7515f7a4f9 | ||
|
|
3e14cd73d4 | ||
|
|
5e4787da1c | ||
|
|
355299fa7d | ||
|
|
5263253279 | ||
|
|
d6bf5f6a97 | ||
|
|
4afcc8f713 | ||
|
|
1472d90599 | ||
|
|
09f7b84634 | ||
|
|
5aa567b6f7 | ||
|
|
1979f24cbb | ||
|
|
6a5e08c48d | ||
|
|
f804442fe4 | ||
|
|
5282013b71 | ||
|
|
4d762a4bc3 | ||
|
|
aac34a9f33 | ||
|
|
406ce0281d | ||
|
|
72cc4b27b0 | ||
|
|
7d188d1776 | ||
|
|
81676df338 | ||
|
|
cfbae0ac37 | ||
|
|
f556b07dce | ||
|
|
8283350471 | ||
|
|
1a7a0291b8 | ||
|
|
38d4003d57 | ||
|
|
bf6c02443a | ||
|
|
e9faf3233c | ||
|
|
9ff1e31776 | ||
|
|
0739cce1e8 | ||
|
|
ef5d9ac398 | ||
|
|
1369f0ca05 | ||
|
|
372546727d | ||
|
|
324039ba0a | ||
|
|
508f6970a5 | ||
|
|
e6a9d9c802 | ||
|
|
21a6c99c5d | ||
|
|
db4d66086a | ||
|
|
c8087bcc70 | ||
|
|
75db2288ca | ||
|
|
cbfc7d9ca3 | ||
|
|
d846be5128 | ||
|
|
15db109d58 | ||
|
|
94d1202726 | ||
|
|
8e78cd925d | ||
|
|
c6b1d83a14 | ||
|
|
b7877514c6 | ||
|
|
370a350353 | ||
|
|
ba58e0e966 | ||
|
|
106b04e076 | ||
|
|
04947a51f3 | ||
|
|
7d96e1e541 | ||
|
|
5003595d8e | ||
|
|
263c5d855a | ||
|
|
36894fd813 | ||
|
|
a22ff2a7c5 | ||
|
|
8c24449b56 | ||
|
|
0994e6c0d2 | ||
|
|
334f20f7fa | ||
|
|
93d3863084 | ||
|
|
e7ecd94635 | ||
|
|
c253b9d27a | ||
|
|
248e3651e3 | ||
|
|
fd4e8f971f |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/es6"],
|
||||
"extends": ["plugin:github/recommended","plugin:@typescript-eslint/recommended"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
@@ -17,13 +17,29 @@
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/ban-ts-ignore": "error",
|
||||
"@typescript-eslint/ban-ts-comment": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/camelcase": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{
|
||||
"selector": "class",
|
||||
"format": ["PascalCase"]
|
||||
},
|
||||
{
|
||||
"selector": "interface",
|
||||
"format": ["PascalCase"]
|
||||
},
|
||||
{
|
||||
"selector": "typeProperty",
|
||||
"format": [],
|
||||
"custom": {
|
||||
"regex": "^[A-Z][A-Za-z]*$",
|
||||
"match": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
@@ -33,7 +49,7 @@
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
||||
"@typescript-eslint/consistent-type-assertions": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
@@ -41,7 +57,7 @@
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-interface": "error",
|
||||
"@typescript-eslint/consistent-type-definitions": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
@@ -50,7 +66,10 @@
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error",
|
||||
"no-console": "off"
|
||||
"no-console": "off",
|
||||
"import/no-unresolved": "off",
|
||||
"sort-imports": "off",
|
||||
"filenames/match-regex": "off"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
|
||||
4
.github/workflows/check-dist.yml
vendored
4
.github/workflows/check-dist.yml
vendored
@@ -24,10 +24,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set Node.js 12.x
|
||||
- name: Set Node.js 16.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 16.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
2
.licenses/npm/rxjs.dep.yml
generated
2
.licenses/npm/rxjs.dep.yml
generated
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: rxjs
|
||||
version: 6.5.4
|
||||
version: 6.6.7
|
||||
type: npm
|
||||
summary: Reactive Extensions for modern JavaScript
|
||||
homepage: https://github.com/ReactiveX/RxJS
|
||||
|
||||
31
README.md
31
README.md
@@ -1,19 +1,17 @@
|
||||
# Delete Package Versions
|
||||
|
||||
This action deletes versions of a package from [GitHub Packages](https://github.com/features/packages).
|
||||
This action deletes versions of a package from [GitHub Packages](https://github.com/features/packages) except ghcr packages. This action will only delete a maximum of 99 versions in one run.
|
||||
|
||||
### What It Can Do
|
||||
|
||||
* Create a retention policy (delete all except n most recent pre-release versions)
|
||||
* Delete all package versions except n most recent versions.
|
||||
* Delete all package versions except n most recent versions
|
||||
* Delete oldest version(s)
|
||||
* Ignore version(s) from deletion through regex.
|
||||
* Ignore version(s) from deletion through regex
|
||||
* Delete version(s) of a package that is hosted in the same repo that is executing the workflow
|
||||
* Delete version(s) of a package that is hosted in a different repo than the one executing the workflow
|
||||
* Delete a single version
|
||||
* Delete multiple versions
|
||||
|
||||
|
||||
* Delete specific version(s)
|
||||
|
||||
# Usage
|
||||
@@ -42,14 +40,12 @@ This action deletes versions of a package from [GitHub Packages](https://github.
|
||||
|
||||
# The number of old versions to delete starting from the oldest version.
|
||||
# Defaults to 1.
|
||||
# Cannot be more than 100.
|
||||
num-old-versions-to-delete:
|
||||
|
||||
# The number of latest versions to not delete.
|
||||
# Defaults to 0.
|
||||
# When this is set greater than 0 it will delete all deletable package versions except the specified no.
|
||||
# `num-old-versions-to-delete` will not be taken into account with this option.
|
||||
# Cannot be more than 100.
|
||||
# The number of latest versions to keep.
|
||||
# This cannot be specified with `num-old-versions-to-delete`. By default, `num-old-versions-to-delete` takes precedence over `min-versions-to-keep`.
|
||||
# When set to 0, all deletable versions will be deleted.
|
||||
# When set greater than 0, all deletable package versions except the specified number will be deleted.
|
||||
min-versions-to-keep:
|
||||
|
||||
# The package versions to exclude from deletion.
|
||||
@@ -61,6 +57,7 @@ This action deletes versions of a package from [GitHub Packages](https://github.
|
||||
# The number of pre-release versions to keep can be set by using `min-versions-to-keep` value with this.
|
||||
# When `min-versions-to-keep` is 0, all pre-release versions get deleted.
|
||||
# Defaults to false.
|
||||
# Cannot be used with `num-old-versions-to-delete` and `ignore-versions`.
|
||||
delete-only-pre-release-versions:
|
||||
|
||||
# The token used to authenticate with GitHub Packages.
|
||||
@@ -71,6 +68,18 @@ This action deletes versions of a package from [GitHub Packages](https://github.
|
||||
token:
|
||||
```
|
||||
|
||||
# Valid Input Combinations
|
||||
|
||||
`owner`, `repo`, `package-name` and `token` can be used with the following combinations in a workflow -
|
||||
|
||||
- `num-old-versions-to-delete`
|
||||
- `min-versions-to-keep`
|
||||
- `delete-only-pre-release-versions`
|
||||
- `ignore-versions`
|
||||
- `num-old-versions-to-delete` + `ignore-versions`
|
||||
- `min-versions-to-keep` + `ignore-versions`
|
||||
- `min-versions-to-keep` + `delete-only-pre-release-versions`
|
||||
|
||||
# Scenarios
|
||||
|
||||
- [Delete all pre-release versions except y latest pre-release package versions](#delete-all-pre-release-versions-except-y-latest-pre-release-package-versions)
|
||||
|
||||
@@ -1,37 +1,40 @@
|
||||
import {Input, InputParams} from '../src/input'
|
||||
import {deleteVersions, getVersionIds} from '../src/delete'
|
||||
import {deleteVersions, finalIds} from '../src/delete'
|
||||
|
||||
describe.skip('index tests -- call graphql', () => {
|
||||
it('getVersionIds test -- get oldest version', done => {
|
||||
it('finalIds test -- get oldest version', done => {
|
||||
const numVersions = 1
|
||||
|
||||
getVersionIds(getInput({numOldVersionsToDelete: numVersions})).subscribe(
|
||||
ids => {
|
||||
expect(ids.length).toBeLessThanOrEqual(numVersions)
|
||||
done()
|
||||
}
|
||||
)
|
||||
finalIds(getInput({numOldVersionsToDelete: numVersions})).subscribe(ids => {
|
||||
expect(ids.length).toBe(numVersions)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('getVersionIds test -- get oldest 3 versions', done => {
|
||||
it.skip('finalIds test -- get oldest 3 versions', done => {
|
||||
const numVersions = 3
|
||||
|
||||
getVersionIds(getInput({numOldVersionsToDelete: numVersions})).subscribe(
|
||||
ids => {
|
||||
expect(ids.length).toBeLessThanOrEqual(numVersions)
|
||||
done()
|
||||
}
|
||||
)
|
||||
finalIds(getInput({numOldVersionsToDelete: numVersions})).subscribe(ids => {
|
||||
expect(ids.length).toBe(numVersions)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('getVersionIds test -- supplied package version id', done => {
|
||||
it.skip('finalIds test -- get oldest 110 versions', done => {
|
||||
const numVersions = 110
|
||||
|
||||
finalIds(getInput({numOldVersionsToDelete: numVersions})).subscribe(ids => {
|
||||
expect(ids.length).toBe(99), async () => done()
|
||||
})
|
||||
})
|
||||
|
||||
it('finalIds test -- supplied package version id', done => {
|
||||
const suppliedIds = [
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB',
|
||||
'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC'
|
||||
]
|
||||
|
||||
getVersionIds(getInput({packageVersionIds: suppliedIds})).subscribe(ids => {
|
||||
finalIds(getInput({packageVersionIds: suppliedIds})).subscribe(ids => {
|
||||
expect(ids).toBe(suppliedIds)
|
||||
done()
|
||||
})
|
||||
@@ -58,28 +61,28 @@ describe.skip('index tests -- call graphql', () => {
|
||||
})
|
||||
|
||||
it.skip('deleteVersions test -- delete oldest version', done => {
|
||||
deleteVersions(
|
||||
getInput({numOldVersionsToDelete: 2, minVersionsToKeep: 1})
|
||||
).subscribe(isSuccess => {
|
||||
expect(isSuccess).toBe(true)
|
||||
done()
|
||||
})
|
||||
deleteVersions(getInput({numOldVersionsToDelete: 1})).subscribe(
|
||||
isSuccess => {
|
||||
expect(isSuccess)
|
||||
},
|
||||
async () => done()
|
||||
)
|
||||
})
|
||||
|
||||
it.skip('deleteVersions test -- delete 3 oldest versions', done => {
|
||||
deleteVersions(
|
||||
getInput({numOldVersionsToDelete: 3, minVersionsToKeep: 1})
|
||||
).subscribe(isSuccess => {
|
||||
expect(isSuccess).toBe(true)
|
||||
done()
|
||||
})
|
||||
deleteVersions(getInput({numOldVersionsToDelete: 3})).subscribe(
|
||||
isSuccess => {
|
||||
expect(isSuccess)
|
||||
},
|
||||
async () => done()
|
||||
)
|
||||
})
|
||||
|
||||
it('deleteVersions test -- keep 5 versions', done => {
|
||||
deleteVersions(getInput({minVersionsToKeep: 5})).subscribe(isSuccess => {
|
||||
it.skip('deleteVersions test -- keep 5 versions', done => {
|
||||
deleteVersions(getInput({minVersionsToKeep: 100})).subscribe(isSuccess => {
|
||||
expect(isSuccess).toBe(true)
|
||||
done()
|
||||
})
|
||||
}),
|
||||
async () => done()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -87,9 +90,10 @@ const defaultInput: InputParams = {
|
||||
packageVersionIds: [],
|
||||
owner: 'namratajha',
|
||||
repo: 'only-pkg',
|
||||
packageName: 'onlypkg.maven',
|
||||
packageName: 'only-pkg',
|
||||
numOldVersionsToDelete: 1,
|
||||
minVersionsToKeep: 1,
|
||||
minVersionsToKeep: -1,
|
||||
ignoreVersions: RegExp('^$'),
|
||||
token: process.env.GITHUB_TOKEN as string
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ const githubToken = process.env.GITHUB_TOKEN as string
|
||||
describe.skip('delete tests', () => {
|
||||
it('deletePackageVersion', async () => {
|
||||
const response = await deletePackageVersion(
|
||||
'MDE0OlBhY2thZ2VWZXJzaW9uNjg5OTU1',
|
||||
'PV_lADOGReZt84AEI7FzgDSHEI',
|
||||
githubToken
|
||||
).toPromise()
|
||||
expect(response).toBe(true)
|
||||
@@ -14,9 +14,9 @@ describe.skip('delete tests', () => {
|
||||
it('deletePackageVersions', async () => {
|
||||
const response = await deletePackageVersions(
|
||||
[
|
||||
'MDE0OlBhY2thZ2VWZXJzaW9uNjk4Mjc0',
|
||||
'MDE0OlBhY2thZ2VWZXJzaW9uNjk4Mjcx',
|
||||
'MDE0OlBhY2thZ2VWZXJzaW9uNjk4MjY3'
|
||||
'PV_lADOGReZt84AEI7FzgDSHDs',
|
||||
'PV_lADOGReZt84AEI7FzgDSHDY',
|
||||
'PV_lADOGReZt84AEI7FzgDSHC8'
|
||||
],
|
||||
githubToken
|
||||
).toPromise()
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
||||
// @ts-ignore
|
||||
import {mockOldestQueryResponse} from './graphql.mock'
|
||||
import {
|
||||
getOldestVersions as _getOldestVersions,
|
||||
VersionInfo
|
||||
QueryInfo
|
||||
} from '../../src/version'
|
||||
import {Observable} from 'rxjs'
|
||||
|
||||
describe.skip('get versions tests -- call graphql', () => {
|
||||
it('getOldestVersions -- succeeds', done => {
|
||||
const numVersions = 1
|
||||
|
||||
getOldestVersions({numVersions}).subscribe(versions => {
|
||||
expect(versions.length).toBe(numVersions)
|
||||
getOldestVersions({numVersions}).subscribe(result => {
|
||||
expect(result.versions.length).toBe(numVersions)
|
||||
done()
|
||||
})
|
||||
})
|
||||
@@ -33,8 +30,8 @@ describe('get versions tests -- mock graphql', () => {
|
||||
const numVersions = 5
|
||||
mockOldestQueryResponse(numVersions)
|
||||
|
||||
getOldestVersions({numVersions}).subscribe(versions => {
|
||||
expect(versions.length).toBe(numVersions)
|
||||
getOldestVersions({numVersions}).subscribe(result => {
|
||||
expect(result.versions.length).toBe(numVersions)
|
||||
done()
|
||||
})
|
||||
})
|
||||
@@ -45,24 +42,27 @@ interface Params {
|
||||
repo?: string
|
||||
packageName?: string
|
||||
numVersions?: number
|
||||
startCursor?: string
|
||||
token?: string
|
||||
}
|
||||
|
||||
const defaultParams = {
|
||||
owner: 'namratajha',
|
||||
repo: 'only-pkg',
|
||||
packageName: 'onlypkg.maven',
|
||||
numVersions: 3,
|
||||
repo: 'test-repo',
|
||||
packageName: 'test-repo',
|
||||
numVersions: 1,
|
||||
startCursor: '',
|
||||
token: process.env.GITHUB_TOKEN as string
|
||||
}
|
||||
|
||||
function getOldestVersions(params?: Params): Observable<VersionInfo[]> {
|
||||
function getOldestVersions(params?: Params): Observable<QueryInfo> {
|
||||
const p: Required<Params> = {...defaultParams, ...params}
|
||||
return _getOldestVersions(
|
||||
p.owner,
|
||||
p.repo,
|
||||
p.packageName,
|
||||
p.numVersions,
|
||||
p.startCursor,
|
||||
p.token
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export function getMockedOldestQueryResponse(
|
||||
numVersions: number
|
||||
): GetVersionsQueryResponse {
|
||||
const versions = []
|
||||
|
||||
numVersions = numVersions < 100 ? numVersions : numVersions
|
||||
for (let i = 1; i <= numVersions; ++i) {
|
||||
versions.push({
|
||||
node: {
|
||||
@@ -28,7 +28,12 @@ export function getMockedOldestQueryResponse(
|
||||
node: {
|
||||
name: 'test',
|
||||
versions: {
|
||||
edges: versions.reverse()
|
||||
totalCount: 200,
|
||||
edges: versions.reverse(),
|
||||
pageInfo: {
|
||||
startCursor: 'AAA',
|
||||
hasPreviousPage: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,12 +43,13 @@ export function getMockedOldestQueryResponse(
|
||||
}
|
||||
}
|
||||
|
||||
export function mockOldestQueryResponse(
|
||||
numVersions: number
|
||||
) {
|
||||
const response = new Promise((resolve) => {
|
||||
export function mockOldestQueryResponse(numVersions: number): void {
|
||||
const response = new Promise<GetVersionsQueryResponse>(resolve => {
|
||||
resolve(getMockedOldestQueryResponse(numVersions))
|
||||
}) as Promise<GraphQlQueryResponseData>
|
||||
jest.spyOn(Graphql, 'graphql').mockImplementation(
|
||||
(token: string, query: string, parameters: RequestParameters) => response)
|
||||
jest
|
||||
.spyOn(Graphql, 'graphql')
|
||||
.mockImplementation(
|
||||
(token: string, query: string, parameters: RequestParameters) => response
|
||||
)
|
||||
}
|
||||
|
||||
11
action.yml
11
action.yml
@@ -37,9 +37,10 @@ inputs:
|
||||
min-versions-to-keep:
|
||||
description: >
|
||||
Number of versions to keep starting with the latest version
|
||||
Defaults to 0.
|
||||
By default keeps no version.
|
||||
To delete all versions set this as 0.
|
||||
required: false
|
||||
default: "0"
|
||||
default: "-1"
|
||||
|
||||
ignore-versions:
|
||||
description: >
|
||||
@@ -50,7 +51,7 @@ inputs:
|
||||
|
||||
delete-only-pre-release-versions:
|
||||
description: >
|
||||
Deletes only pre-release versions upto. The number of pre-release versions to keep can be specified by min-versions-to-keep.
|
||||
Deletes only pre-release versions. The number of pre-release versions to keep can be specified by min-versions-to-keep.
|
||||
When this is set num-old-versions-to-delete and ignore-versions will not be taken into account.
|
||||
By default this is set to false
|
||||
required: false
|
||||
@@ -66,9 +67,9 @@ inputs:
|
||||
default: ${{ github.token }}
|
||||
|
||||
runs:
|
||||
using: node12
|
||||
using: node16
|
||||
main: dist/index.js
|
||||
|
||||
branding:
|
||||
icon: package
|
||||
color: blue
|
||||
color: blue
|
||||
|
||||
13331
dist/index.js
vendored
13331
dist/index.js
vendored
File diff suppressed because one or more lines are too long
6927
package-lock.json
generated
6927
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -7,9 +7,10 @@
|
||||
"scripts": {
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"lint": "eslint src/**/*.ts --fix",
|
||||
"lint-check": "eslint src/**/*.ts",
|
||||
"test": "jest",
|
||||
"build": "npm run format-check && npm run lint && npm run test && tsc",
|
||||
"build": "npm run format-check && npm run lint-check && npm run test && tsc",
|
||||
"pack": "rm -rf ./lib ./dist && npm run build && ncc build"
|
||||
},
|
||||
"repository": {
|
||||
@@ -29,12 +30,12 @@
|
||||
"rxjs": "^6.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.23",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/node": "^12.7.12",
|
||||
"@typescript-eslint/parser": "^2.8.0",
|
||||
"@vercel/ncc": "^0.31.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-github": "^2.0.0",
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-plugin-github": "^4.3.5",
|
||||
"eslint-plugin-jest": "^22.21.0",
|
||||
"jest": "^27.3.1",
|
||||
"jest-circus": "^27.3.1",
|
||||
|
||||
166
src/delete.ts
166
src/delete.ts
@@ -1,46 +1,130 @@
|
||||
import {Input} from './input'
|
||||
import {Observable, of, throwError} from 'rxjs'
|
||||
import {deletePackageVersions, getOldestVersions} from './version'
|
||||
import {concatMap, map} from 'rxjs/operators'
|
||||
import {EMPTY, Observable, of, throwError} from 'rxjs'
|
||||
import {deletePackageVersions, getOldestVersions, VersionInfo} from './version'
|
||||
import {concatMap, map, expand, tap} from 'rxjs/operators'
|
||||
|
||||
export function getVersionIds(input: Input): Observable<string[]> {
|
||||
const RATE_LIMIT = 99
|
||||
let totalCount = 0
|
||||
|
||||
export function getVersionIds(
|
||||
owner: string,
|
||||
repo: string,
|
||||
packageName: string,
|
||||
numVersions: number,
|
||||
cursor: string,
|
||||
token: string
|
||||
): Observable<VersionInfo[]> {
|
||||
return getOldestVersions(
|
||||
owner,
|
||||
repo,
|
||||
packageName,
|
||||
numVersions,
|
||||
cursor,
|
||||
token
|
||||
).pipe(
|
||||
expand(value =>
|
||||
value.paginate
|
||||
? getOldestVersions(
|
||||
owner,
|
||||
repo,
|
||||
packageName,
|
||||
numVersions,
|
||||
value.cursor,
|
||||
token
|
||||
)
|
||||
: EMPTY
|
||||
),
|
||||
tap(
|
||||
value => (totalCount = totalCount === 0 ? value.totalCount : totalCount)
|
||||
),
|
||||
map(value => value.versions)
|
||||
)
|
||||
}
|
||||
|
||||
export function finalIds(input: Input): Observable<string[]> {
|
||||
if (input.packageVersionIds.length > 0) {
|
||||
return of(input.packageVersionIds)
|
||||
}
|
||||
|
||||
if (input.hasOldestVersionQueryInfo()) {
|
||||
return getOldestVersions(
|
||||
input.owner,
|
||||
input.repo,
|
||||
input.packageName,
|
||||
input.numOldVersionsToDelete + input.minVersionsToKeep,
|
||||
input.token
|
||||
).pipe(
|
||||
map(versionInfo => {
|
||||
const numberVersionsToDelete =
|
||||
versionInfo.length - input.minVersionsToKeep
|
||||
|
||||
if (input.minVersionsToKeep > 0) {
|
||||
return numberVersionsToDelete <= 0
|
||||
? []
|
||||
: versionInfo
|
||||
.filter(info => !input.ignoreVersions.test(info.version))
|
||||
.map(info => info.id)
|
||||
.slice(0, -input.minVersionsToKeep)
|
||||
} else {
|
||||
return numberVersionsToDelete <= 0
|
||||
? []
|
||||
: versionInfo
|
||||
.filter(info => !input.ignoreVersions.test(info.version))
|
||||
.map(info => info.id)
|
||||
.slice(0, numberVersionsToDelete)
|
||||
}
|
||||
})
|
||||
)
|
||||
if (input.minVersionsToKeep < 0) {
|
||||
// This code block is when num-old-versions-to-delete is specified.
|
||||
// Setting input.numOldVersionsToDelete is set as minimum of input.numOldVersionsToDelete and RATE_LIMIT
|
||||
input.numOldVersionsToDelete =
|
||||
input.numOldVersionsToDelete < RATE_LIMIT
|
||||
? input.numOldVersionsToDelete
|
||||
: RATE_LIMIT
|
||||
return getVersionIds(
|
||||
input.owner,
|
||||
input.repo,
|
||||
input.packageName,
|
||||
RATE_LIMIT,
|
||||
'',
|
||||
input.token
|
||||
).pipe(
|
||||
// This code block executes on batches of 100 versions starting from oldest
|
||||
map(value => {
|
||||
/*
|
||||
Here first filter out the versions that are to be ignored.
|
||||
Then update input.numOldeVersionsToDelete to the no of versions deleted from the next 100 versions batch.
|
||||
*/
|
||||
value = value.filter(info => !input.ignoreVersions.test(info.version))
|
||||
const temp = input.numOldVersionsToDelete
|
||||
input.numOldVersionsToDelete =
|
||||
input.numOldVersionsToDelete - value.length <= 0
|
||||
? 0
|
||||
: input.numOldVersionsToDelete - value.length
|
||||
return value.map(info => info.id).slice(0, temp)
|
||||
})
|
||||
)
|
||||
} else {
|
||||
// This code block is when min-versions-to-keep is specified.
|
||||
return getVersionIds(
|
||||
input.owner,
|
||||
input.repo,
|
||||
input.packageName,
|
||||
RATE_LIMIT,
|
||||
'',
|
||||
input.token
|
||||
).pipe(
|
||||
// This code block executes on batches of 100 versions starting from oldest
|
||||
map(value => {
|
||||
/*
|
||||
Here totalCount is the total no of versions in the package.
|
||||
First we update totalCount by removing no of ignored versions from it and also filter them out from value.
|
||||
toDelete is the no of versions that need to be deleted and input.numDeleted is the total no of versions deleted before this batch.
|
||||
We calculate this from total no of versions in the package, the min no of versions to keep and the no of versions we have deleted in earlier batch.
|
||||
Then we update toDelete to not exceed the length of current batch of versions.
|
||||
Now toDelete holds the no of versions to be deleted from the current batch of versions.
|
||||
*/
|
||||
totalCount =
|
||||
totalCount -
|
||||
value.filter(info => input.ignoreVersions.test(info.version)).length
|
||||
value = value.filter(info => !input.ignoreVersions.test(info.version))
|
||||
let toDelete = totalCount - input.minVersionsToKeep - input.numDeleted
|
||||
toDelete = toDelete > value.length ? value.length : toDelete
|
||||
//Checking here if we have any versions to delete and whether we are within the RATE_LIMIT.
|
||||
if (toDelete > 0 && input.numDeleted < RATE_LIMIT) {
|
||||
/*
|
||||
Checking here if we can delete all the versions left in the current batch.
|
||||
input.numDeleted + toDelete should not exceed RATE_LIMIT.
|
||||
If it is exceeding we only delete the no of versions from this batch that are allowed within the RATE_LIMIT.
|
||||
i.e. diff between RATE_LIMIT and versions deleted till now (input.numDeleted)
|
||||
input.numDeleted is updated accordingly.
|
||||
*/
|
||||
if (input.numDeleted + toDelete > RATE_LIMIT) {
|
||||
toDelete = RATE_LIMIT - input.numDeleted
|
||||
input.numDeleted = RATE_LIMIT
|
||||
} else {
|
||||
input.numDeleted = input.numDeleted + toDelete
|
||||
}
|
||||
return value.map(info => info.id).slice(0, toDelete)
|
||||
} else return []
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return throwError(
|
||||
"Could not get packageVersionIds. Explicitly specify using the 'package-version-ids' input or provide the 'package-name' and 'num-old-versions-to-delete' inputs to dynamically retrieve oldest versions"
|
||||
"Could not get packageVersionIds. Explicitly specify using the 'package-version-ids' input"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -49,14 +133,18 @@ export function deleteVersions(input: Input): Observable<boolean> {
|
||||
return throwError('No token found')
|
||||
}
|
||||
|
||||
if (input.numOldVersionsToDelete <= 0) {
|
||||
if (!input.checkInput()) {
|
||||
return throwError('Invalid input combination')
|
||||
}
|
||||
|
||||
if (input.numOldVersionsToDelete <= 0 && input.minVersionsToKeep < 0) {
|
||||
console.log(
|
||||
'Number of old versions to delete input is 0 or less, no versions will be deleted'
|
||||
)
|
||||
return of(true)
|
||||
}
|
||||
|
||||
return getVersionIds(input).pipe(
|
||||
concatMap(ids => deletePackageVersions(ids, input.token))
|
||||
)
|
||||
const result = finalIds(input)
|
||||
|
||||
return result.pipe(concatMap(ids => deletePackageVersions(ids, input.token)))
|
||||
}
|
||||
|
||||
35
src/input.ts
35
src/input.ts
@@ -32,6 +32,7 @@ export class Input {
|
||||
ignoreVersions: RegExp
|
||||
deletePreReleaseVersions: string
|
||||
token: string
|
||||
numDeleted: number
|
||||
|
||||
constructor(params?: InputParams) {
|
||||
const validatedParams: Required<InputParams> = {...defaultParams, ...params}
|
||||
@@ -45,15 +46,7 @@ export class Input {
|
||||
this.ignoreVersions = validatedParams.ignoreVersions
|
||||
this.deletePreReleaseVersions = validatedParams.deletePreReleaseVersions
|
||||
this.token = validatedParams.token
|
||||
|
||||
if (this.minVersionsToKeep > 0) {
|
||||
this.numOldVersionsToDelete = 100 - this.minVersionsToKeep
|
||||
}
|
||||
|
||||
if (this.deletePreReleaseVersions == 'true') {
|
||||
this.numOldVersionsToDelete = 100 - this.minVersionsToKeep
|
||||
this.ignoreVersions = new RegExp('^(0|[1-9]\\d*)((\\.(0|[1-9]\\d*))*)$')
|
||||
}
|
||||
this.numDeleted = 0
|
||||
}
|
||||
|
||||
hasOldestVersionQueryInfo(): boolean {
|
||||
@@ -61,9 +54,29 @@ export class Input {
|
||||
this.owner &&
|
||||
this.repo &&
|
||||
this.packageName &&
|
||||
this.numOldVersionsToDelete > 0 &&
|
||||
this.minVersionsToKeep >= 0 &&
|
||||
this.numOldVersionsToDelete >= 0 &&
|
||||
this.token
|
||||
)
|
||||
}
|
||||
|
||||
checkInput(): boolean {
|
||||
if (
|
||||
this.numOldVersionsToDelete > 1 &&
|
||||
(this.minVersionsToKeep >= 0 || this.deletePreReleaseVersions === 'true')
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (this.deletePreReleaseVersions === 'true') {
|
||||
this.minVersionsToKeep =
|
||||
this.minVersionsToKeep > 0 ? this.minVersionsToKeep : 0
|
||||
this.ignoreVersions = new RegExp('^(0|[1-9]\\d*)((\\.(0|[1-9]\\d*))*)$')
|
||||
}
|
||||
|
||||
if (this.minVersionsToKeep >= 0) {
|
||||
this.numOldVersionsToDelete = 0
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import {from, Observable, merge, throwError, of} from 'rxjs'
|
||||
import {catchError, map, tap} from 'rxjs/operators'
|
||||
import {GraphQlQueryResponse} from '@octokit/graphql/dist-types/types'
|
||||
import {graphql} from './graphql'
|
||||
|
||||
let deleted = 0
|
||||
|
||||
export interface DeletePackageVersionMutationResponse {
|
||||
deletePackageVersion: {
|
||||
success: boolean
|
||||
@@ -10,7 +12,7 @@ export interface DeletePackageVersionMutationResponse {
|
||||
}
|
||||
|
||||
const mutation = `
|
||||
mutation deletePackageVersion($packageVersionId: String!) {
|
||||
mutation deletePackageVersion($packageVersionId: ID!) {
|
||||
deletePackageVersion(input: {packageVersionId: $packageVersionId}) {
|
||||
success
|
||||
}
|
||||
@@ -20,6 +22,7 @@ export function deletePackageVersion(
|
||||
packageVersionId: string,
|
||||
token: string
|
||||
): Observable<boolean> {
|
||||
deleted += 1
|
||||
return from(
|
||||
graphql(token, mutation, {
|
||||
packageVersionId,
|
||||
@@ -28,12 +31,12 @@ export function deletePackageVersion(
|
||||
}
|
||||
}) as Promise<DeletePackageVersionMutationResponse>
|
||||
).pipe(
|
||||
catchError((err: GraphQlQueryResponse) => {
|
||||
catchError(err => {
|
||||
const msg = 'delete version mutation failed.'
|
||||
return throwError(
|
||||
err.errors && err.errors.length > 0
|
||||
? `${msg} ${err.errors[0].message}`
|
||||
: `${msg} verify input parameters are correct`
|
||||
: `${msg} ${err.message} \n${deleted - 1} versions deleted till now.`
|
||||
)
|
||||
}),
|
||||
map(response => response.deletePackageVersion.success)
|
||||
@@ -45,21 +48,18 @@ export function deletePackageVersions(
|
||||
token: string
|
||||
): Observable<boolean> {
|
||||
if (packageVersionIds.length === 0) {
|
||||
console.log('no package version ids found, no versions will be deleted')
|
||||
return of(true)
|
||||
}
|
||||
|
||||
const deletes = packageVersionIds.map(id =>
|
||||
deletePackageVersion(id, token).pipe(
|
||||
tap(result => {
|
||||
if (result) {
|
||||
console.log(`version with id: ${id}, deleted`)
|
||||
} else {
|
||||
if (!result) {
|
||||
console.log(`version with id: ${id}, not deleted`)
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
console.log(`Total versions deleted till now: ${deleted}`)
|
||||
return merge(...deletes)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import {GraphQlQueryResponse} from '@octokit/graphql/dist-types/types'
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import {Observable, from, throwError} from 'rxjs'
|
||||
import {catchError, map} from 'rxjs/operators'
|
||||
import {graphql} from './graphql'
|
||||
@@ -8,6 +10,13 @@ export interface VersionInfo {
|
||||
version: string
|
||||
}
|
||||
|
||||
export interface QueryInfo {
|
||||
versions: VersionInfo[]
|
||||
cursor: string
|
||||
paginate: boolean
|
||||
totalCount: number
|
||||
}
|
||||
|
||||
export interface GetVersionsQueryResponse {
|
||||
repository: {
|
||||
packages: {
|
||||
@@ -15,7 +24,12 @@ export interface GetVersionsQueryResponse {
|
||||
node: {
|
||||
name: string
|
||||
versions: {
|
||||
totalCount: number
|
||||
edges: {node: VersionInfo}[]
|
||||
pageInfo: {
|
||||
startCursor: string
|
||||
hasPreviousPage: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
}[]
|
||||
@@ -31,12 +45,43 @@ const query = `
|
||||
node {
|
||||
name
|
||||
versions(last: $last) {
|
||||
totalCount
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
version
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
startCursor
|
||||
hasPreviousPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
const Paginatequery = `
|
||||
query getVersions($owner: String!, $repo: String!, $package: String!, $last: Int!, $before: String!) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
packages(first: 1, names: [$package]) {
|
||||
edges {
|
||||
node {
|
||||
name
|
||||
versions(last: $last, before: $before) {
|
||||
totalCount
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
version
|
||||
}
|
||||
}
|
||||
pageInfo{
|
||||
startCursor
|
||||
hasPreviousPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,28 +94,53 @@ export function queryForOldestVersions(
|
||||
repo: string,
|
||||
packageName: string,
|
||||
numVersions: number,
|
||||
startCursor: string,
|
||||
token: string
|
||||
): Observable<GetVersionsQueryResponse> {
|
||||
return from(
|
||||
graphql(token, query, {
|
||||
owner,
|
||||
repo,
|
||||
package: packageName,
|
||||
last: numVersions,
|
||||
headers: {
|
||||
Accept: 'application/vnd.github.packages-preview+json'
|
||||
}
|
||||
}) as Promise<GetVersionsQueryResponse>
|
||||
).pipe(
|
||||
catchError((err: GraphQlQueryResponse) => {
|
||||
const msg = 'query for oldest version failed.'
|
||||
return throwError(
|
||||
err.errors && err.errors.length > 0
|
||||
? `${msg} ${err.errors[0].message}`
|
||||
: `${msg} verify input parameters are correct`
|
||||
)
|
||||
})
|
||||
)
|
||||
if (startCursor === '') {
|
||||
return from(
|
||||
graphql(token, query, {
|
||||
owner,
|
||||
repo,
|
||||
package: packageName,
|
||||
last: numVersions,
|
||||
headers: {
|
||||
Accept: 'application/vnd.github.packages-preview+json'
|
||||
}
|
||||
}) as Promise<GetVersionsQueryResponse>
|
||||
).pipe(
|
||||
catchError((err: GraphQlQueryResponse<unknown>) => {
|
||||
const msg = 'query for oldest version failed.'
|
||||
return throwError(
|
||||
err.errors && err.errors.length > 0
|
||||
? `${msg} ${err.errors[0].message}`
|
||||
: `${msg} verify input parameters are correct`
|
||||
)
|
||||
})
|
||||
)
|
||||
} else {
|
||||
return from(
|
||||
graphql(token, Paginatequery, {
|
||||
owner,
|
||||
repo,
|
||||
package: packageName,
|
||||
last: numVersions,
|
||||
before: startCursor,
|
||||
headers: {
|
||||
Accept: 'application/vnd.github.packages-preview+json'
|
||||
}
|
||||
}) as Promise<GetVersionsQueryResponse>
|
||||
).pipe(
|
||||
catchError((err: GraphQlQueryResponse<unknown>) => {
|
||||
const msg = 'query for oldest version failed.'
|
||||
return throwError(
|
||||
err.errors && err.errors.length > 0
|
||||
? `${msg} ${err.errors[0].message}`
|
||||
: `${msg} verify input parameters are correct`
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function getOldestVersions(
|
||||
@@ -78,34 +148,46 @@ export function getOldestVersions(
|
||||
repo: string,
|
||||
packageName: string,
|
||||
numVersions: number,
|
||||
startCursor: string,
|
||||
token: string
|
||||
): Observable<VersionInfo[]> {
|
||||
): Observable<QueryInfo> {
|
||||
return queryForOldestVersions(
|
||||
owner,
|
||||
repo,
|
||||
packageName,
|
||||
numVersions,
|
||||
startCursor,
|
||||
token
|
||||
).pipe(
|
||||
map(result => {
|
||||
let r: QueryInfo
|
||||
if (result.repository.packages.edges.length < 1) {
|
||||
console.log(
|
||||
`package: ${packageName} not found for owner: ${owner} in repo: ${repo}`
|
||||
)
|
||||
return []
|
||||
r = {
|
||||
versions: [] as VersionInfo[],
|
||||
cursor: '',
|
||||
paginate: false,
|
||||
totalCount: 0
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
const versions = result.repository.packages.edges[0].node.versions.edges
|
||||
const pages = result.repository.packages.edges[0].node.versions.pageInfo
|
||||
const count = result.repository.packages.edges[0].node.versions.totalCount
|
||||
|
||||
if (versions.length !== numVersions) {
|
||||
console.log(
|
||||
`number of versions requested was: ${numVersions}, but found: ${versions.length}`
|
||||
)
|
||||
r = {
|
||||
versions: versions
|
||||
.map(value => ({id: value.node.id, version: value.node.version}))
|
||||
.reverse(),
|
||||
cursor: pages.startCursor,
|
||||
paginate: pages.hasPreviousPage,
|
||||
totalCount: count
|
||||
}
|
||||
|
||||
return versions
|
||||
.map(value => ({id: value.node.id, version: value.node.version}))
|
||||
.reverse()
|
||||
return r
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import {GitHub} from '@actions/github'
|
||||
import {GraphQlQueryResponseData} from '@octokit/graphql/dist-types/types'
|
||||
import {RequestParameters} from '@octokit/types/dist-types/RequestParameters'
|
||||
|
||||
Reference in New Issue
Block a user