get versions using rest

This commit is contained in:
Anupam
2022-12-28 14:43:50 +00:00
parent cc7196aa1d
commit e521d9e753
5 changed files with 113 additions and 413 deletions
-68
View File
@@ -1,68 +0,0 @@
import {mockOldestQueryResponse} from './graphql.mock'
import {
getOldestVersions as _getOldestVersions,
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(result => {
expect(result.versions.length).toBe(numVersions)
done()
})
})
it('getOldestVersions -- fails for invalid repo', done => {
getOldestVersions({repo: 'actions-testin'}).subscribe({
error: err => {
expect(err).toBeTruthy()
done()
},
complete: async () => done.fail('no error thrown')
})
})
})
describe('get versions tests -- mock graphql', () => {
it('getOldestVersions -- success', done => {
const numVersions = 5
mockOldestQueryResponse(numVersions)
getOldestVersions({numVersions}).subscribe(result => {
expect(result.versions.length).toBe(numVersions)
done()
})
})
})
interface Params {
owner?: string
repo?: string
packageName?: string
numVersions?: number
startCursor?: string
token?: string
}
const defaultParams = {
owner: 'namratajha',
repo: 'test-repo',
packageName: 'test-repo',
numVersions: 1,
startCursor: '',
token: process.env.GITHUB_TOKEN as string
}
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
)
}
+38 -153
View File
@@ -21,9 +21,9 @@ const version_1 = __nccwpck_require__(4428);
const operators_1 = __nccwpck_require__(7801); const operators_1 = __nccwpck_require__(7801);
const RATE_LIMIT = 99; const RATE_LIMIT = 99;
let totalCount = 0; let totalCount = 0;
function getVersionIds(owner, repo, packageName, numVersions, cursor, token) { function getVersionIds(owner, packageName, packageType, numVersions, page, token) {
return version_1.getOldestVersions(owner, repo, packageName, numVersions, cursor, token).pipe(operators_1.expand(value => value.paginate return version_1.getOldestVersions(owner, packageName, packageType, numVersions, page, token).pipe(operators_1.expand(value => value.paginate
? version_1.getOldestVersions(owner, repo, packageName, numVersions, value.cursor, token) ? version_1.getOldestVersions(owner, packageName, packageType, numVersions, value.page, token)
: rxjs_1.EMPTY), operators_1.tap(value => (totalCount = totalCount === 0 ? value.totalCount : totalCount)), operators_1.map(value => value.versions)); : rxjs_1.EMPTY), operators_1.tap(value => (totalCount = totalCount === 0 ? value.totalCount : totalCount)), operators_1.map(value => value.versions));
} }
exports.getVersionIds = getVersionIds; exports.getVersionIds = getVersionIds;
@@ -39,7 +39,7 @@ function finalIds(input) {
input.numOldVersionsToDelete < RATE_LIMIT input.numOldVersionsToDelete < RATE_LIMIT
? input.numOldVersionsToDelete ? input.numOldVersionsToDelete
: RATE_LIMIT; : RATE_LIMIT;
return getVersionIds(input.owner, input.repo, input.packageName, RATE_LIMIT, '', input.token).pipe( return getVersionIds(input.owner, input.packageName, input.packageType, RATE_LIMIT, 1, input.token).pipe(
// This code block executes on batches of 100 versions starting from oldest // This code block executes on batches of 100 versions starting from oldest
operators_1.map(value => { operators_1.map(value => {
/* /*
@@ -52,12 +52,12 @@ function finalIds(input) {
input.numOldVersionsToDelete - value.length <= 0 input.numOldVersionsToDelete - value.length <= 0
? 0 ? 0
: input.numOldVersionsToDelete - value.length; : input.numOldVersionsToDelete - value.length;
return value.map(info => info.id).slice(0, temp); return value.map(info => info.id.toString()).slice(0, temp);
})); }));
} }
else { else {
// This code block is when min-versions-to-keep is specified. // This code block is when min-versions-to-keep is specified.
return getVersionIds(input.owner, input.repo, input.packageName, RATE_LIMIT, '', input.token).pipe( return getVersionIds(input.owner, input.packageName, input.packageType, RATE_LIMIT, 1, input.token).pipe(
// This code block executes on batches of 100 versions starting from oldest // This code block executes on batches of 100 versions starting from oldest
operators_1.map(value => { operators_1.map(value => {
/* /*
@@ -90,7 +90,7 @@ function finalIds(input) {
else { else {
input.numDeleted = input.numDeleted + toDelete; input.numDeleted = input.numDeleted + toDelete;
} }
return value.map(info => info.id).slice(0, toDelete); return value.map(info => info.id.toString()).slice(0, toDelete);
} }
else else
return []; return [];
@@ -278,163 +278,44 @@ exports.deletePackageVersions = deletePackageVersions;
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getOldestVersions = exports.queryForOldestVersions = void 0; exports.getOldestVersions = void 0;
// eslint-disable-next-line @typescript-eslint/no-unused-vars /* eslint-disable @typescript-eslint/no-unused-vars */
const rxjs_1 = __nccwpck_require__(5805); const rxjs_1 = __nccwpck_require__(5805);
const operators_1 = __nccwpck_require__(7801); const operators_1 = __nccwpck_require__(7801);
const graphql_1 = __nccwpck_require__(6320); const rest_1 = __nccwpck_require__(5375);
const query = ` function getOldestVersions(owner, packageName, packageType, numVersions, page, token) {
query getVersions($owner: String!, $repo: String!, $package: String!, $last: Int!) { const octokit = new rest_1.Octokit({
repository(owner: $owner, name: $repo) { auth: token
packages(first: 1, names: [$package]) { });
edges { const package_type = packageType;
node { return rxjs_1.from(octokit.rest.packages.getAllPackageVersionsForPackageOwnedByUser({
name package_type,
versions(last: $last) { package_name: packageName,
totalCount username: owner,
edges { per_page: numVersions,
node { page
id })).pipe(operators_1.catchError(err => {
version const msg = 'get versions API failed.';
}
}
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
}
}
}
}
}
}
}`;
function queryForOldestVersions(owner, repo, packageName, numVersions, startCursor, token) {
if (startCursor === '') {
return rxjs_1.from(graphql_1.graphql(token, query, {
owner,
repo,
package: packageName,
last: numVersions,
headers: {
Accept: 'application/vnd.github.packages-preview+json'
}
})).pipe(operators_1.catchError((err) => {
const msg = 'query for oldest version failed.';
return rxjs_1.throwError(err.errors && err.errors.length > 0 return rxjs_1.throwError(err.errors && err.errors.length > 0
? `${msg} ${err.errors[0].message}` ? `${msg} ${err.errors[0].message}`
: `${msg} verify input parameters are correct`); : `${msg} ${err.message}`);
})); }), operators_1.map(response => {
} return {
else { versions: response.data.map((version) => {
return rxjs_1.from(graphql_1.graphql(token, Paginatequery, { return {
owner, id: version.id,
repo, version: version.name
package: packageName,
last: numVersions,
before: startCursor,
headers: {
Accept: 'application/vnd.github.packages-preview+json'
}
})).pipe(operators_1.catchError((err) => {
const msg = 'query for oldest version failed.';
return rxjs_1.throwError(err.errors && err.errors.length > 0
? `${msg} ${err.errors[0].message}`
: `${msg} verify input parameters are correct`);
}));
}
}
exports.queryForOldestVersions = queryForOldestVersions;
function getOldestVersions(owner, repo, packageName, numVersions, startCursor, token) {
return queryForOldestVersions(owner, repo, packageName, numVersions, startCursor, token).pipe(operators_1.map(result => {
let r;
if (result.repository.packages.edges.length < 1) {
console.log(`package: ${packageName} not found for owner: ${owner} in repo: ${repo}`);
r = {
versions: [],
cursor: '',
paginate: false,
totalCount: 0
}; };
return r; }),
} page: page + 1,
const versions = result.repository.packages.edges[0].node.versions.edges; paginate: response.data.length === numVersions,
const pages = result.repository.packages.edges[0].node.versions.pageInfo; totalCount: response.data.length
const count = result.repository.packages.edges[0].node.versions.totalCount;
r = {
versions: versions
.map(value => ({ id: value.node.id, version: value.node.version }))
.reverse(),
cursor: pages.startCursor,
paginate: pages.hasPreviousPage,
totalCount: count
}; };
return r;
})); }));
} }
exports.getOldestVersions = getOldestVersions; exports.getOldestVersions = getOldestVersions;
/***/ }),
/***/ 6320:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.graphql = void 0;
/* eslint-disable @typescript-eslint/no-unused-vars */
const github_1 = __nccwpck_require__(5438);
/**
* Sends a GraphQL query request based on endpoint options
*
* @param {string} token Auth token
* @param {string} query GraphQL query. Example: `'query { viewer { login } }'`.
* @param {object} parameters URL, query or body parameters, as well as `headers`, `mediaType.{format|previews}`, `request`, or `baseUrl`.
*/
function graphql(token, query, parameters) {
return __awaiter(this, void 0, void 0, function* () {
const github = new github_1.GitHub(token);
return yield github.graphql(query, parameters);
});
}
exports.graphql = graphql;
/***/ }), /***/ }),
/***/ 4428: /***/ 4428:
@@ -44091,6 +43972,7 @@ var __webpack_exports__ = {};
var exports = __webpack_exports__; var exports = __webpack_exports__;
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
/* eslint-disable @typescript-eslint/no-unused-vars */
const core_1 = __nccwpck_require__(2186); const core_1 = __nccwpck_require__(2186);
const github_1 = __nccwpck_require__(5438); const github_1 = __nccwpck_require__(5438);
const input_1 = __nccwpck_require__(8657); const input_1 = __nccwpck_require__(8657);
@@ -44119,8 +44001,11 @@ function run() {
return delete_1.deleteVersions(getActionInput()).pipe(operators_1.catchError(err => rxjs_1.throwError(err))); return delete_1.deleteVersions(getActionInput()).pipe(operators_1.catchError(err => rxjs_1.throwError(err)));
} }
catch (error) { catch (error) {
if (error instanceof Error) {
return rxjs_1.throwError(error.message); return rxjs_1.throwError(error.message);
} }
return rxjs_1.throwError(error);
}
} }
run().subscribe({ run().subscribe({
error: err => { error: err => {
+20 -14
View File
@@ -1,6 +1,12 @@
/* eslint-disable i18n-text/no-en */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {Input} from './input' import {Input} from './input'
import {EMPTY, Observable, of, throwError} from 'rxjs' import {EMPTY, Observable, of, throwError} from 'rxjs'
import {deletePackageVersions, getOldestVersions, VersionInfo} from './version' import {
deletePackageVersions,
getOldestVersions,
RestVersionInfo
} from './version'
import {concatMap, map, expand, tap} from 'rxjs/operators' import {concatMap, map, expand, tap} from 'rxjs/operators'
const RATE_LIMIT = 99 const RATE_LIMIT = 99
@@ -8,28 +14,28 @@ let totalCount = 0
export function getVersionIds( export function getVersionIds(
owner: string, owner: string,
repo: string,
packageName: string, packageName: string,
packageType: string,
numVersions: number, numVersions: number,
cursor: string, page: number,
token: string token: string
): Observable<VersionInfo[]> { ): Observable<RestVersionInfo[]> {
return getOldestVersions( return getOldestVersions(
owner, owner,
repo,
packageName, packageName,
packageType,
numVersions, numVersions,
cursor, page,
token token
).pipe( ).pipe(
expand(value => expand(value =>
value.paginate value.paginate
? getOldestVersions( ? getOldestVersions(
owner, owner,
repo,
packageName, packageName,
packageType,
numVersions, numVersions,
value.cursor, value.page,
token token
) )
: EMPTY : EMPTY
@@ -55,10 +61,10 @@ export function finalIds(input: Input): Observable<string[]> {
: RATE_LIMIT : RATE_LIMIT
return getVersionIds( return getVersionIds(
input.owner, input.owner,
input.repo,
input.packageName, input.packageName,
input.packageType,
RATE_LIMIT, RATE_LIMIT,
'', 1,
input.token input.token
).pipe( ).pipe(
// This code block executes on batches of 100 versions starting from oldest // This code block executes on batches of 100 versions starting from oldest
@@ -73,17 +79,17 @@ export function finalIds(input: Input): Observable<string[]> {
input.numOldVersionsToDelete - value.length <= 0 input.numOldVersionsToDelete - value.length <= 0
? 0 ? 0
: input.numOldVersionsToDelete - value.length : input.numOldVersionsToDelete - value.length
return value.map(info => info.id).slice(0, temp) return value.map(info => info.id.toString()).slice(0, temp)
}) })
) )
} else { } else {
// This code block is when min-versions-to-keep is specified. // This code block is when min-versions-to-keep is specified.
return getVersionIds( return getVersionIds(
input.owner, input.owner,
input.repo,
input.packageName, input.packageName,
input.packageType,
RATE_LIMIT, RATE_LIMIT,
'', 1,
input.token input.token
).pipe( ).pipe(
// This code block executes on batches of 100 versions starting from oldest // This code block executes on batches of 100 versions starting from oldest
@@ -117,7 +123,7 @@ export function finalIds(input: Input): Observable<string[]> {
} else { } else {
input.numDeleted = input.numDeleted + toDelete input.numDeleted = input.numDeleted + toDelete
} }
return value.map(info => info.id).slice(0, toDelete) return value.map(info => info.id.toString()).slice(0, toDelete)
} else return [] } else return []
}) })
) )
+4
View File
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {getInput, setFailed} from '@actions/core' import {getInput, setFailed} from '@actions/core'
import {context} from '@actions/github' import {context} from '@actions/github'
import {Input} from './input' import {Input} from './input'
@@ -31,8 +32,11 @@ function run(): Observable<boolean> {
catchError(err => throwError(err)) catchError(err => throwError(err))
) )
} catch (error) { } catch (error) {
if (error instanceof Error) {
return throwError(error.message) return throwError(error.message)
} }
return throwError(error)
}
} }
run().subscribe({ run().subscribe({
+44 -171
View File
@@ -1,193 +1,66 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars /* eslint-disable @typescript-eslint/no-unused-vars */
import {GraphQlQueryResponse} from '@octokit/graphql/dist-types/types' import {from, Observable, merge, throwError, of} from 'rxjs'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import {Observable, from, throwError} from 'rxjs'
import {catchError, map} from 'rxjs/operators' import {catchError, map} from 'rxjs/operators'
import {graphql} from './graphql' import {Octokit} from '@octokit/rest'
import {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods/dist-types/generated/parameters-and-response-types'
export interface VersionInfo { export interface RestVersionInfo {
id: string id: number
version: string version: string
} }
export interface QueryInfo { export interface RestQueryInfo {
versions: VersionInfo[] versions: RestVersionInfo[]
cursor: string page: number
paginate: boolean paginate: boolean
totalCount: number totalCount: number
} }
export interface GetVersionsQueryResponse { type PackageType = RestEndpointMethodTypes['packages']['getAllPackageVersionsForPackageOwnedByUser']['parameters']['package_type']
repository: { type GetVersionsResponse = RestEndpointMethodTypes['packages']['getAllPackageVersionsForPackageOwnedByUser']['response']['data']
packages: {
edges: {
node: {
name: string
versions: {
totalCount: number
edges: {node: VersionInfo}[]
pageInfo: {
startCursor: string
hasPreviousPage: boolean
}
}
}
}[]
}
}
}
const query = `
query getVersions($owner: String!, $repo: String!, $package: String!, $last: Int!) {
repository(owner: $owner, name: $repo) {
packages(first: 1, names: [$package]) {
edges {
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
}
}
}
}
}
}
}`
export function queryForOldestVersions(
owner: string,
repo: string,
packageName: string,
numVersions: number,
startCursor: string,
token: string
): Observable<GetVersionsQueryResponse> {
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( export function getOldestVersions(
owner: string, owner: string,
repo: string,
packageName: string, packageName: string,
packageType: string,
numVersions: number, numVersions: number,
startCursor: string, page: number,
token: string token: string
): Observable<QueryInfo> { ): Observable<RestQueryInfo> {
return queryForOldestVersions( const octokit = new Octokit({
owner, auth: token
repo, })
packageName, const package_type: PackageType = packageType as PackageType
numVersions,
startCursor, return from(
token octokit.rest.packages.getAllPackageVersionsForPackageOwnedByUser({
package_type,
package_name: packageName,
username: owner,
per_page: numVersions,
page
})
).pipe( ).pipe(
map(result => { catchError(err => {
let r: QueryInfo const msg = 'get versions API failed.'
if (result.repository.packages.edges.length < 1) { return throwError(
console.log( err.errors && err.errors.length > 0
`package: ${packageName} not found for owner: ${owner} in repo: ${repo}` ? `${msg} ${err.errors[0].message}`
: `${msg} ${err.message}`
) )
r = { }),
versions: [] as VersionInfo[], map(response => {
cursor: '', return {
paginate: false, versions: response.data.map((version: GetVersionsResponse[0]) => {
totalCount: 0 return {
id: version.id,
version: version.name
} }
return r }),
page: page + 1,
paginate: response.data.length === numVersions,
totalCount: response.data.length
} }
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
r = {
versions: versions
.map(value => ({id: value.node.id, version: value.node.version}))
.reverse(),
cursor: pages.startCursor,
paginate: pages.hasPreviousPage,
totalCount: count
}
return r
}) })
) )
} }