diff --git a/README.md b/README.md index ffa908dd..36a7c732 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ This action deletes versions of a package from [GitHub Packages](https://github. * Delete all package versions except n most recent versions * Delete oldest version(s) * 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 version(s) of packages that are hosted in the same repo that is executing the workflow +* Delete version(s) of packages that are hosted in a different repo than the one executing the workflow * Delete a single version * Delete multiple versions * Delete specific version(s) @@ -35,9 +35,20 @@ This action deletes versions of a package from [GitHub Packages](https://github. # Name of the package. # Defaults to an empty string. - # Required if `package-version-ids` input is not given. + # Required if `package-version-ids` or `package-names` input is not given. package-name: + # Names of the package. + # Can be one of the following: + # - a single package name + # - a group of packages that matches a wildcard at start, end, both sides, or all packages (e.g. "package*") + # - a group of packages that matches a regex, must start with slash at the beginning and end (e.g. "/package.*/") + # - a comma separated list of the previous cases (e.g. "package-lorem, *-ipsum, /.*dolor/") + # Defaults to an empty string. + # Required if `package-version-ids` or `package-name` input is not given. + package-names: + + # The number of old versions to delete starting from the oldest version. # Defaults to 1. num-old-versions-to-delete: @@ -70,7 +81,7 @@ This action deletes versions of a package from [GitHub Packages](https://github. # Valid Input Combinations -`owner`, `repo`, `package-name` and `token` can be used with the following combinations in a workflow - +`owner`, `repo`, `package-name` (or `package-names`) and `token` can be used with the following combinations in a workflow - - `num-old-versions-to-delete` - `min-versions-to-keep` @@ -86,12 +97,13 @@ This action deletes versions of a package from [GitHub Packages](https://github. - [Delete all except y latest versions while ignoring particular package versions](#delete-all-except-y-latest-versions-while-ignoring-particular-package-versions) - [Delete oldest x number of versions while ignoring particular package versions](#delete-oldest-x-number-of-versions-while-ignoring-particular-package-versions) - [Delete all except y latest versions of a package](#delete-all-except-y-latest-versions-of-a-package) + - [Delete all except y latest versions of all packages in a repo](#delete-all-except-y-latest-versions-of-all-packages-in-a-repo) - [Delete oldest x number of versions of a package](#delete-oldest-x-number-of-versions-of-a-package) - [Delete oldest version of a package](#delete-oldest-version-of-a-package) - [Delete a specific version of a package](#delete-a-specific-version-of-a-package) - [Delete multiple specific versions of a package](#delete-multiple-specific-versions-of-a-package) - + ### Delete all pre-release versions except y latest pre-release package versions To delete all pre release versions except y latest pre-release package versions in the same repo as the workflow the __package-name__, __min-versions-to-keep__ and __delete-only-pre-release-versions__ inputs are required. @@ -241,6 +253,41 @@ This action deletes versions of a package from [GitHub Packages](https://github.
+ ### Delete all except y latest versions of a package + + To delete all except y latest versions of all packages hosted in the same repo as the workflow the __package-names__ and __min-versions-to-keep__ inputs are required. + + __Example__ + + Delete all except latest 2 versions of a package hosted in the same repo as the workflow + + ```yaml + - uses: actions/delete-package-versions@v3 + with: + package-names: '*' + min-versions-to-keep: 2 + ``` + + To delete all except y latest versions of all packages hosted in a repo other than the workflow the __owner__, __repo__, __package-names__, __token__ and __min-versions-to-keep__ inputs are required. + + The [token][token] needs the delete packages and read packages scope. It is recommended [to store the token as a secret][secret]. In this example the [token][token] was stored as a secret named __GITHUB_PAT__. + + __Example__ + + Delete all except latest 2 versions of a package hosted in a repo other than the workflow + + ```yaml + - uses: actions/delete-package-versions@v3 + with: + owner: 'github' + repo: 'packages' + package-names: '*' + token: ${{ secrets.PAT }} + min-versions-to-keep: 2 + ``` + +
+ ### Delete oldest x number of versions of a package To delete the oldest x number of versions of a package hosted in the same repo as the workflow the __package-name__, and __num-old-versions-to-delete__ inputs are required. diff --git a/__tests__/packages/get-packages.test.ts b/__tests__/packages/get-packages.test.ts new file mode 100644 index 00000000..27672257 --- /dev/null +++ b/__tests__/packages/get-packages.test.ts @@ -0,0 +1,66 @@ +import {mockPackagesQueryResponse} from './graphql.mock' +import { + getRepoPackages as _getRepoPackages, + QueryInfo +} from '../../src/packages' +import {Observable} from 'rxjs' + +describe.skip('get versions tests -- call graphql', () => { + it('getRepoPackages -- succeeds', done => { + const numPackages = 1 + getRepoPackages({numPackages}).subscribe(result => { + expect(result.packages.length).toBe(numPackages) + done() + }) + }) + + it('getRepoPackages -- fails for invalid repo', done => { + getRepoPackages({repo: 'actions-testin'}).subscribe({ + error: err => { + expect(err).toBeTruthy() + done() + }, + complete: async () => done.fail('no error thrown') + }) + }) + }) + + describe('get versions tests -- mock graphql', () => { + it('getRepoPackages -- success', done => { + const numPackages = 5 + mockPackagesQueryResponse(numPackages) + + getRepoPackages({numPackages}).subscribe(result => { + expect(result.packages.length).toBe(numPackages) + done() + }) + }) + }) + + interface Params { + owner?: string + repo?: string + numPackages?: number + startCursor?: string + token?: string + } + + const defaultParams = { + owner: 'namratajha', + repo: 'test-repo', + packageName: 'test-repo', + numPackages: 1, + startCursor: '', + token: process.env.GITHUB_TOKEN as string + } + + function getRepoPackages(params?: Params): Observable { + const p: Required = {...defaultParams, ...params} + return _getRepoPackages( + p.owner, + p.repo, + p.numPackages, + p.startCursor, + p.token + ) + } \ No newline at end of file diff --git a/__tests__/packages/graphql.mock.ts b/__tests__/packages/graphql.mock.ts new file mode 100644 index 00000000..181434c7 --- /dev/null +++ b/__tests__/packages/graphql.mock.ts @@ -0,0 +1,44 @@ +import { + GraphQlQueryResponseData, + RequestParameters +} from '@octokit/graphql/dist-types/types' + +import * as Graphql from '../../src/common/graphql' +import {GetPackagesQueryResponse} from '../../src/packages' + +export function getMockedPackagesQueryResponse( + numPackages: number +): GetPackagesQueryResponse { + const packages = [] + for (let i = 1; i <= numPackages; ++i) { + packages.push({ + node: { + id: i.toString(), + name: `package${i}` + } + }) + } + + return { + repository: { + packages: { + pageInfo: { + endCursor: 'AAA', + hasNextPage: false + }, + edges: packages + } + } + } +} + +export function mockPackagesQueryResponse(numVersions: number): void { + const response = new Promise(resolve => { + resolve(getMockedPackagesQueryResponse(numVersions)) + }) as Promise + jest + .spyOn(Graphql, 'graphql') + .mockImplementation( + (token: string, query: string, parameters: RequestParameters) => response + ) +} diff --git a/__tests__/packages/package-name-filter.test.ts b/__tests__/packages/package-name-filter.test.ts new file mode 100644 index 00000000..781d7c74 --- /dev/null +++ b/__tests__/packages/package-name-filter.test.ts @@ -0,0 +1,114 @@ +import { getPackageNameFilter } from '../../src/packages' + +describe('package name filter -- create filter', () => { + + const packageNameList = [ + 'com.company.project.module1.package1', + 'com.company.project.module1.package2', + 'com.company.project.module2.package1', + 'com.company.project.module2.package2', + 'com.company.project.module3.package-name-lorem', + 'com.company.project.module3.package-name-ipsum', + 'com.company.project.module3.package-name-dolor', + ] + + it('getPackageNameFilter -- wildcard end filter', done => { + const filter = getPackageNameFilter('com.company.project.module1.*') + + const result = packageNameList.filter(filter.apply); + + expect(filter.subfilters[0].type).toBe('wildcard') + expect(result).toEqual([ + 'com.company.project.module1.package1', + 'com.company.project.module1.package2', + ]) + done() + }) + + it('getPackageNameFilter -- wildcard start filter', done => { + const filter = getPackageNameFilter('*.package1') + + const result = packageNameList.filter(filter.apply); + + expect(filter.subfilters[0].type).toBe('wildcard') + expect(result).toEqual([ + 'com.company.project.module1.package1', + 'com.company.project.module2.package1', + ]) + done() + }) + + it('getPackageNameFilter -- wildcard both sides filter', done => { + const filter = getPackageNameFilter('*.project.module3.*') + + const result = packageNameList.filter(filter.apply); + + expect(filter.subfilters[0].type).toBe('wildcard') + expect(result).toEqual([ + 'com.company.project.module3.package-name-lorem', + 'com.company.project.module3.package-name-ipsum', + 'com.company.project.module3.package-name-dolor' + ]) + done() + }) + + + it('getPackageNameFilter -- wildcard all filter', done => { + const filter = getPackageNameFilter('*') + + const result = packageNameList.filter(filter.apply); + + expect(filter.subfilters[0].type).toBe('wildcard') + expect(result).toEqual(packageNameList.slice()) + done() + }) + + it('getPackageNameFilter -- regex filter', done => { + const filter = getPackageNameFilter('/com\\.company\\.project\\.module.*\\.package1/') + const result = packageNameList.filter(filter.apply); + + expect(filter.subfilters[0].type).toBe('regex') + expect(result).toEqual([ + 'com.company.project.module1.package1', + 'com.company.project.module2.package1', + ]) + done() + }) + + it('getPackageNameFilter -- exact match filter', done => { + const filter = getPackageNameFilter('com.company.project.module1.package1') + const result = packageNameList.filter(filter.apply); + + expect(filter.subfilters[0].type).toBe('string') + expect(result).toEqual(['com.company.project.module1.package1']) + done() + }) + + + it('getPackageNameFilter -- multiple filters', done => { + const filter = getPackageNameFilter('com.company.project.module1.package1, com.company.project.module2.*, /.*module3.*-ipsum/') + const result = packageNameList.filter(filter.apply); + + expect(filter.subfilters.length).toBe(3) + expect(filter.subfilters[0].type).toBe('string') + expect(filter.subfilters[1].type).toBe('wildcard') + expect(filter.subfilters[2].type).toBe('regex') + expect(result).toEqual([ + 'com.company.project.module1.package1', + 'com.company.project.module2.package1', + 'com.company.project.module2.package2', + 'com.company.project.module3.package-name-ipsum' + ]) + done() + }) + + + it('getPackageNameFilter -- memoization, same input shoud return same output', done => { + const filterText = 'com.company.project.module1.package1, com.company.project.module2.*, /.*module3.*-dolor/, *.-lorem' + const filter1 = getPackageNameFilter(filterText) + const filter2 = getPackageNameFilter(filterText) + expect(filter1).toBe(filter2) + expect(filter1.subfilters.length).toBe(4) + done() + }) + }) \ No newline at end of file diff --git a/__tests__/version/graphql.mock.ts b/__tests__/version/graphql.mock.ts index c2fb04e7..0e47abe7 100644 --- a/__tests__/version/graphql.mock.ts +++ b/__tests__/version/graphql.mock.ts @@ -3,7 +3,7 @@ import { RequestParameters } from '@octokit/graphql/dist-types/types' -import * as Graphql from '../../src/version/graphql' +import * as Graphql from '../../src/common/graphql' import {GetVersionsQueryResponse} from '../../src/version' export function getMockedOldestQueryResponse( diff --git a/action.yml b/action.yml index 519a3b8f..2837de93 100644 --- a/action.yml +++ b/action.yml @@ -27,6 +27,19 @@ inputs: Required if dynamically deleting oldest versions. required: false + + package-names: + description: > + Names of the package. + Can be one of the following: + - a single package name + - a group of packages that matches a wildcard at start, end, both sides, or all packages (e.g. "package*") + - a group of packages that matches a regex, must start with slash at the beginning and end (e.g. "/package.*/") + - a comma separated list of the previous cases (e.g. "package-lorem, *-ipsum, /.*dolor/") + Defaults to an empty string. + Required if `package-version-ids` or `package-name` input is not given. + required: false + num-old-versions-to-delete: description: > Number of versions to delete starting with the oldest version. diff --git a/dist/index.js b/dist/index.js index ee3c486f..79fbfcc6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5,7 +5,43 @@ /***/ ((module) => { "use strict"; -module.exports = JSON.parse('{"_args":[["@octokit/rest@16.43.2","/workspaces/delete-package-versions"]],"_from":"@octokit/rest@16.43.2","_id":"@octokit/rest@16.43.2","_inBundle":false,"_integrity":"sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==","_location":"/@octokit/rest","_phantomChildren":{"deprecation":"2.3.1","once":"1.4.0","os-name":"3.1.0"},"_requested":{"type":"version","registry":true,"raw":"@octokit/rest@16.43.2","name":"@octokit/rest","escapedName":"@octokit%2frest","scope":"@octokit","rawSpec":"16.43.2","saveSpec":null,"fetchSpec":"16.43.2"},"_requiredBy":["/@actions/github"],"_resolved":"https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz","_spec":"16.43.2","_where":"/workspaces/delete-package-versions","author":{"name":"Gregor Martynus","url":"https://github.com/gr2m"},"bugs":{"url":"https://github.com/octokit/rest.js/issues"},"bundlesize":[{"path":"./dist/octokit-rest.min.js.gz","maxSize":"33 kB"}],"contributors":[{"name":"Mike de Boer","email":"info@mikedeboer.nl"},{"name":"Fabian Jakobs","email":"fabian@c9.io"},{"name":"Joe Gallo","email":"joe@brassafrax.com"},{"name":"Gregor Martynus","url":"https://github.com/gr2m"}],"dependencies":{"@octokit/auth-token":"^2.4.0","@octokit/plugin-paginate-rest":"^1.1.1","@octokit/plugin-request-log":"^1.0.0","@octokit/plugin-rest-endpoint-methods":"2.4.0","@octokit/request":"^5.2.0","@octokit/request-error":"^1.0.2","atob-lite":"^2.0.0","before-after-hook":"^2.0.0","btoa-lite":"^1.0.0","deprecation":"^2.0.0","lodash.get":"^4.4.2","lodash.set":"^4.3.2","lodash.uniq":"^4.5.0","octokit-pagination-methods":"^1.1.0","once":"^1.4.0","universal-user-agent":"^4.0.0"},"description":"GitHub REST API client for Node.js","devDependencies":{"@gimenete/type-writer":"^0.1.3","@octokit/auth":"^1.1.1","@octokit/fixtures-server":"^5.0.6","@octokit/graphql":"^4.2.0","@types/node":"^13.1.0","bundlesize":"^0.18.0","chai":"^4.1.2","compression-webpack-plugin":"^3.1.0","cypress":"^4.0.0","glob":"^7.1.2","http-proxy-agent":"^4.0.0","lodash.camelcase":"^4.3.0","lodash.merge":"^4.6.1","lodash.upperfirst":"^4.3.1","lolex":"^6.0.0","mkdirp":"^1.0.0","mocha":"^7.0.1","mustache":"^4.0.0","nock":"^11.3.3","npm-run-all":"^4.1.2","nyc":"^15.0.0","prettier":"^1.14.2","proxy":"^1.0.0","semantic-release":"^17.0.0","sinon":"^8.0.0","sinon-chai":"^3.0.0","sort-keys":"^4.0.0","string-to-arraybuffer":"^1.0.0","string-to-jsdoc-comment":"^1.0.0","typescript":"^3.3.1","webpack":"^4.0.0","webpack-bundle-analyzer":"^3.0.0","webpack-cli":"^3.0.0"},"files":["index.js","index.d.ts","lib","plugins"],"homepage":"https://github.com/octokit/rest.js#readme","keywords":["octokit","github","rest","api-client"],"license":"MIT","name":"@octokit/rest","nyc":{"ignore":["test"]},"publishConfig":{"access":"public"},"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"repository":{"type":"git","url":"git+https://github.com/octokit/rest.js.git"},"scripts":{"build":"npm-run-all build:*","build:browser":"npm-run-all build:browser:*","build:browser:development":"webpack --mode development --entry . --output-library=Octokit --output=./dist/octokit-rest.js --profile --json > dist/bundle-stats.json","build:browser:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=Octokit --output-path=./dist --output-filename=octokit-rest.min.js --devtool source-map","build:ts":"npm run -s update-endpoints:typescript","coverage":"nyc report --reporter=html && open coverage/index.html","generate-bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","lint":"prettier --check \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","lint:fix":"prettier --write \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","postvalidate:ts":"tsc --noEmit --target es6 test/typescript-validate.ts","prebuild:browser":"mkdirp dist/","pretest":"npm run -s lint","prevalidate:ts":"npm run -s build:ts","start-fixtures-server":"octokit-fixtures-server","test":"nyc mocha test/mocha-node-setup.js \\"test/*/**/*-test.js\\"","test:browser":"cypress run --browser chrome","update-endpoints":"npm-run-all update-endpoints:*","update-endpoints:fetch-json":"node scripts/update-endpoints/fetch-json","update-endpoints:typescript":"node scripts/update-endpoints/typescript","validate:ts":"tsc --target es6 --noImplicitAny index.d.ts"},"types":"index.d.ts","version":"16.43.2"}'); +module.exports = JSON.parse('{"_args":[["@octokit/rest@16.43.2","/home/omar/workspace/git/delete-package-versions"]],"_from":"@octokit/rest@16.43.2","_id":"@octokit/rest@16.43.2","_inBundle":false,"_integrity":"sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==","_location":"/@octokit/rest","_phantomChildren":{"deprecation":"2.3.1","once":"1.4.0","os-name":"3.1.0"},"_requested":{"type":"version","registry":true,"raw":"@octokit/rest@16.43.2","name":"@octokit/rest","escapedName":"@octokit%2frest","scope":"@octokit","rawSpec":"16.43.2","saveSpec":null,"fetchSpec":"16.43.2"},"_requiredBy":["/@actions/github"],"_resolved":"https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz","_spec":"16.43.2","_where":"/home/omar/workspace/git/delete-package-versions","author":{"name":"Gregor Martynus","url":"https://github.com/gr2m"},"bugs":{"url":"https://github.com/octokit/rest.js/issues"},"bundlesize":[{"path":"./dist/octokit-rest.min.js.gz","maxSize":"33 kB"}],"contributors":[{"name":"Mike de Boer","email":"info@mikedeboer.nl"},{"name":"Fabian Jakobs","email":"fabian@c9.io"},{"name":"Joe Gallo","email":"joe@brassafrax.com"},{"name":"Gregor Martynus","url":"https://github.com/gr2m"}],"dependencies":{"@octokit/auth-token":"^2.4.0","@octokit/plugin-paginate-rest":"^1.1.1","@octokit/plugin-request-log":"^1.0.0","@octokit/plugin-rest-endpoint-methods":"2.4.0","@octokit/request":"^5.2.0","@octokit/request-error":"^1.0.2","atob-lite":"^2.0.0","before-after-hook":"^2.0.0","btoa-lite":"^1.0.0","deprecation":"^2.0.0","lodash.get":"^4.4.2","lodash.set":"^4.3.2","lodash.uniq":"^4.5.0","octokit-pagination-methods":"^1.1.0","once":"^1.4.0","universal-user-agent":"^4.0.0"},"description":"GitHub REST API client for Node.js","devDependencies":{"@gimenete/type-writer":"^0.1.3","@octokit/auth":"^1.1.1","@octokit/fixtures-server":"^5.0.6","@octokit/graphql":"^4.2.0","@types/node":"^13.1.0","bundlesize":"^0.18.0","chai":"^4.1.2","compression-webpack-plugin":"^3.1.0","cypress":"^4.0.0","glob":"^7.1.2","http-proxy-agent":"^4.0.0","lodash.camelcase":"^4.3.0","lodash.merge":"^4.6.1","lodash.upperfirst":"^4.3.1","lolex":"^6.0.0","mkdirp":"^1.0.0","mocha":"^7.0.1","mustache":"^4.0.0","nock":"^11.3.3","npm-run-all":"^4.1.2","nyc":"^15.0.0","prettier":"^1.14.2","proxy":"^1.0.0","semantic-release":"^17.0.0","sinon":"^8.0.0","sinon-chai":"^3.0.0","sort-keys":"^4.0.0","string-to-arraybuffer":"^1.0.0","string-to-jsdoc-comment":"^1.0.0","typescript":"^3.3.1","webpack":"^4.0.0","webpack-bundle-analyzer":"^3.0.0","webpack-cli":"^3.0.0"},"files":["index.js","index.d.ts","lib","plugins"],"homepage":"https://github.com/octokit/rest.js#readme","keywords":["octokit","github","rest","api-client"],"license":"MIT","name":"@octokit/rest","nyc":{"ignore":["test"]},"publishConfig":{"access":"public"},"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"repository":{"type":"git","url":"git+https://github.com/octokit/rest.js.git"},"scripts":{"build":"npm-run-all build:*","build:browser":"npm-run-all build:browser:*","build:browser:development":"webpack --mode development --entry . --output-library=Octokit --output=./dist/octokit-rest.js --profile --json > dist/bundle-stats.json","build:browser:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=Octokit --output-path=./dist --output-filename=octokit-rest.min.js --devtool source-map","build:ts":"npm run -s update-endpoints:typescript","coverage":"nyc report --reporter=html && open coverage/index.html","generate-bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","lint":"prettier --check \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","lint:fix":"prettier --write \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","postvalidate:ts":"tsc --noEmit --target es6 test/typescript-validate.ts","prebuild:browser":"mkdirp dist/","pretest":"npm run -s lint","prevalidate:ts":"npm run -s build:ts","start-fixtures-server":"octokit-fixtures-server","test":"nyc mocha test/mocha-node-setup.js \\"test/*/**/*-test.js\\"","test:browser":"cypress run --browser chrome","update-endpoints":"npm-run-all update-endpoints:*","update-endpoints:fetch-json":"node scripts/update-endpoints/fetch-json","update-endpoints:typescript":"node scripts/update-endpoints/typescript","validate:ts":"tsc --target es6 --noImplicitAny index.d.ts"},"types":"index.d.ts","version":"16.43.2"}'); + +/***/ }), + +/***/ 9057: +/***/ (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; + /***/ }), @@ -15,9 +51,11 @@ module.exports = JSON.parse('{"_args":[["@octokit/rest@16.43.2","/workspaces/del "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.deleteVersions = exports.finalIds = exports.getVersionIds = void 0; +exports.deleteVersions = exports.finalIds = exports.getPackageNames = exports.getVersionIds = void 0; +const input_1 = __nccwpck_require__(8657); const rxjs_1 = __nccwpck_require__(5805); const version_1 = __nccwpck_require__(4428); +const packages_1 = __nccwpck_require__(221); const operators_1 = __nccwpck_require__(7801); const RATE_LIMIT = 99; let totalCount = 0; @@ -27,11 +65,27 @@ function getVersionIds(owner, repo, packageName, numVersions, cursor, token) { : rxjs_1.EMPTY), operators_1.tap(value => (totalCount = totalCount === 0 ? value.totalCount : totalCount)), operators_1.map(value => value.versions)); } exports.getVersionIds = getVersionIds; +function getPackageNames(owner, repo, numPackages, cursor, token) { + return packages_1.getRepoPackages(owner, repo, numPackages, cursor, token).pipe(operators_1.expand(value => value.paginate + ? packages_1.getRepoPackages(owner, repo, numPackages, value.cursor, token) + : rxjs_1.EMPTY), operators_1.map(value => value.packages)); +} +exports.getPackageNames = getPackageNames; function finalIds(input) { if (input.packageVersionIds.length > 0) { return rxjs_1.of(input.packageVersionIds); } if (input.hasOldestVersionQueryInfo()) { + const filter = packages_1.getPackageNameFilter(input.packageNames); + if (!filter.isEmpty) { + return getPackageNames(input.owner, input.repo, RATE_LIMIT, '', input.token) + .pipe(operators_1.mergeMap(value => { + return value + .filter(info => filter.apply(info.name)) + .map(info => finalIds(new input_1.Input(Object.assign(Object.assign({}, input), { packageNames: '', packageName: info.name })))); + })) + .pipe(operators_1.mergeMap(val => val)); + } 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 @@ -131,6 +185,7 @@ const defaultParams = { owner: '', repo: '', packageName: '', + packageNames: '', numOldVersionsToDelete: 0, minVersionsToKeep: 0, ignoreVersions: new RegExp(''), @@ -144,6 +199,7 @@ class Input { this.owner = validatedParams.owner; this.repo = validatedParams.repo; this.packageName = validatedParams.packageName; + this.packageNames = validatedParams.packageNames; this.numOldVersionsToDelete = validatedParams.numOldVersionsToDelete; this.minVersionsToKeep = validatedParams.minVersionsToKeep; this.ignoreVersions = validatedParams.ignoreVersions; @@ -154,7 +210,7 @@ class Input { hasOldestVersionQueryInfo() { return !!(this.owner && this.repo && - this.packageName && + (this.packageName || this.packageNames) && this.numOldVersionsToDelete >= 0 && this.token); } @@ -177,6 +233,245 @@ class Input { exports.Input = Input; +/***/ }), + +/***/ 6436: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRepoPackages = exports.queryForRepoPackages = void 0; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const rxjs_1 = __nccwpck_require__(5805); +const operators_1 = __nccwpck_require__(7801); +const graphql_1 = __nccwpck_require__(9057); +const query = ` + query getPackages($owner: String!, $repo: String!, $first: Int!){ + repository(owner: $owner, name: $repo) { + packages(first:$first){ + edges { + node { + name + id + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + }`; +const Paginatequery = ` + query getPackages($owner: String!, $repo: String!, $first: Int!, $after: String!){ + repository(owner: $owner, name: $repo) { + packages(first:$first){ + edges { + node { + name + id + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + }`; +function queryForRepoPackages(owner, repo, numPackages, startCursor, token) { + if (startCursor === '') { + return rxjs_1.from(graphql_1.graphql(token, query, { + owner, + repo, + first: numPackages, + headers: { + Accept: 'application/vnd.github.packages-preview+json' + } + })).pipe(operators_1.catchError((err) => { + const msg = 'query for packages failed.'; + return rxjs_1.throwError(err.errors && err.errors.length > 0 + ? `${msg} ${err.errors[0].message}` + : `${msg} verify input parameters are correct ${JSON.stringify(err, null, 2)}`); + })); + } + else { + return rxjs_1.from(graphql_1.graphql(token, Paginatequery, { + owner, + repo, + first: numPackages, + before: startCursor, + headers: { + Accept: 'application/vnd.github.packages-preview+json' + } + })).pipe(operators_1.catchError((err) => { + const msg = 'query for packages failed.'; + return rxjs_1.throwError(err.errors && err.errors.length > 0 + ? `${msg} ${err.errors[0].message}` + : `${msg} verify input parameters are correct`); + })); + } +} +exports.queryForRepoPackages = queryForRepoPackages; +function getRepoPackages(owner, repo, numPackages, startCursor, token) { + return queryForRepoPackages(owner, repo, numPackages, startCursor, token).pipe(operators_1.map(result => { + let r; + if (result.repository.packages.edges.length < 1) { + console.log(`package: No packages found for owner: ${owner} in repo: ${repo}`); + r = { + packages: [], + cursor: '', + paginate: false + }; + return r; + } + const packages = result.repository.packages.edges; + const pages = result.repository.packages.pageInfo; + r = { + packages: packages.map(value => ({ + id: value.node.id, + name: value.node.name + })), + cursor: pages.endCursor, + paginate: pages.hasNextPage + }; + return r; + })); +} +exports.getRepoPackages = getRepoPackages; + + +/***/ }), + +/***/ 221: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__nccwpck_require__(6436), exports); +__exportStar(__nccwpck_require__(2539), exports); + + +/***/ }), + +/***/ 2539: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getPackageNameFilter = void 0; +/** + * Used to apply memoization on getPackageNameFilter + */ +const resultCache = {}; +/** + * Get a filter based on package names to match + * + * @param packageNames - serialized package names filter as string + * @returns the respective package filter + */ +function getPackageNameFilter(packageNames) { + if (resultCache[packageNames]) { + return resultCache[packageNames]; + } + const result = calculatePackageNameFilter(packageNames); + resultCache[packageNames] = result; + return result; +} +exports.getPackageNameFilter = getPackageNameFilter; +const emptyFilter = Object.freeze({ + subfilters: Object.freeze([]), + isEmpty: true, + apply: () => false +}); +/** + * Generates a filter based package names to match + * + * @param packageNames - serialized package names filter as string + * @returns the respective package filter + */ +function calculatePackageNameFilter(packageNames) { + if (packageNames === '') { + return emptyFilter; + } + const separatedPackageNames = packageNames + .split(',') + .map(name => name.trim()) + .filter(name => name !== ''); + if (separatedPackageNames.length <= 0) { + return emptyFilter; + } + const subfilters = separatedPackageNames.map(createFilter); + return { + subfilters, + isEmpty: subfilters.length <= 0, + apply: names => subfilters.some(filter => filter.apply(names)) + }; +} +function createFilter(packageName) { + if (packageName.startsWith('*') || packageName.endsWith('*')) { + return createWildcardFilter(packageName); + } + else if (packageName.startsWith('/') && packageName.endsWith('/')) { + return createRegexFilter(packageName); + } + else { + return createExactMatchFilter(packageName); + } +} +function createWildcardFilter(wildcardPackageName) { + const startsWithWildCard = wildcardPackageName.startsWith('*'); + const endsWithWildCard = wildcardPackageName.endsWith('*'); + let fn; + if (wildcardPackageName === '*') { + fn = () => true; + } + else if (startsWithWildCard && endsWithWildCard) { + const targetText = wildcardPackageName.substring(1, wildcardPackageName.length - 1); + fn = (packageName) => packageName.includes(targetText); + } + else if (startsWithWildCard) { + const targetText = wildcardPackageName.substring(1); + fn = (packageName) => packageName.endsWith(targetText); + } + else { + const targetText = wildcardPackageName.substring(0, wildcardPackageName.length - 1); + fn = (packageName) => packageName.startsWith(targetText); + } + return { + type: 'wildcard', + apply: fn + }; +} +function createRegexFilter(regexPackageName) { + const regexPattern = regexPackageName.substring(1, regexPackageName.length - 1); + const regex = new RegExp(regexPattern); + return { + type: 'regex', + apply: (packageName) => regex.test(packageName) + }; +} +function createExactMatchFilter(matchingPackageName) { + return { + type: 'string', + apply: (packageName) => packageName === matchingPackageName + }; +} + + /***/ }), /***/ 5544: @@ -189,7 +484,7 @@ exports.deletePackageVersions = exports.deletePackageVersion = void 0; // eslint-disable-next-line @typescript-eslint/no-unused-vars const rxjs_1 = __nccwpck_require__(5805); const operators_1 = __nccwpck_require__(7801); -const graphql_1 = __nccwpck_require__(6320); +const graphql_1 = __nccwpck_require__(9057); let deleted = 0; const mutation = ` mutation deletePackageVersion($packageVersionId: ID!) { @@ -239,7 +534,7 @@ exports.getOldestVersions = exports.queryForOldestVersions = void 0; // eslint-disable-next-line @typescript-eslint/no-unused-vars const rxjs_1 = __nccwpck_require__(5805); const operators_1 = __nccwpck_require__(7801); -const graphql_1 = __nccwpck_require__(6320); +const graphql_1 = __nccwpck_require__(9057); const query = ` query getVersions($owner: String!, $repo: String!, $package: String!, $last: Int!) { repository(owner: $owner, name: $repo) { @@ -356,42 +651,6 @@ function getOldestVersions(owner, repo, packageName, numVersions, startCursor, t 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: @@ -40071,6 +40330,7 @@ function getActionInput() { owner: core_1.getInput('owner') ? core_1.getInput('owner') : github_1.context.repo.owner, repo: core_1.getInput('repo') ? core_1.getInput('repo') : github_1.context.repo.repo, packageName: core_1.getInput('package-name'), + packageNames: core_1.getInput('package-names'), numOldVersionsToDelete: Number(core_1.getInput('num-old-versions-to-delete')), minVersionsToKeep: Number(core_1.getInput('min-versions-to-keep')), ignoreVersions: RegExp(core_1.getInput('ignore-versions')), diff --git a/src/version/graphql.ts b/src/common/graphql.ts similarity index 100% rename from src/version/graphql.ts rename to src/common/graphql.ts diff --git a/src/delete.ts b/src/delete.ts index c2f9c3c6..05c18990 100644 --- a/src/delete.ts +++ b/src/delete.ts @@ -1,7 +1,8 @@ import {Input} from './input' import {EMPTY, Observable, of, throwError} from 'rxjs' import {deletePackageVersions, getOldestVersions, VersionInfo} from './version' -import {concatMap, map, expand, tap} from 'rxjs/operators' +import {getRepoPackages, getPackageNameFilter, PackageInfo} from './packages' +import {concatMap, map, mergeMap, expand, tap} from 'rxjs/operators' const RATE_LIMIT = 99 let totalCount = 0 @@ -41,11 +42,55 @@ export function getVersionIds( ) } +export function getPackageNames( + owner: string, + repo: string, + numPackages: number, + cursor: string, + token: string +): Observable { + return getRepoPackages(owner, repo, numPackages, cursor, token).pipe( + expand(value => + value.paginate + ? getRepoPackages(owner, repo, numPackages, value.cursor, token) + : EMPTY + ), + map(value => value.packages) + ) +} + export function finalIds(input: Input): Observable { if (input.packageVersionIds.length > 0) { return of(input.packageVersionIds) } if (input.hasOldestVersionQueryInfo()) { + const filter = getPackageNameFilter(input.packageNames) + if (!filter.isEmpty) { + return getPackageNames( + input.owner, + input.repo, + RATE_LIMIT, + '', + input.token + ) + .pipe( + mergeMap(value => { + return value + .filter(info => filter.apply(info.name)) + .map(info => + finalIds( + new Input({ + ...input, + packageNames: '', + packageName: info.name + }) + ) + ) + }) + ) + .pipe(mergeMap(val => val)) + } + 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 diff --git a/src/input.ts b/src/input.ts index 35244d52..aa349821 100644 --- a/src/input.ts +++ b/src/input.ts @@ -3,6 +3,7 @@ export interface InputParams { owner?: string repo?: string packageName?: string + packageNames?: string numOldVersionsToDelete?: number minVersionsToKeep?: number ignoreVersions?: RegExp @@ -15,6 +16,7 @@ const defaultParams = { owner: '', repo: '', packageName: '', + packageNames: '', numOldVersionsToDelete: 0, minVersionsToKeep: 0, ignoreVersions: new RegExp(''), @@ -27,6 +29,7 @@ export class Input { owner: string repo: string packageName: string + packageNames: string numOldVersionsToDelete: number minVersionsToKeep: number ignoreVersions: RegExp @@ -41,6 +44,7 @@ export class Input { this.owner = validatedParams.owner this.repo = validatedParams.repo this.packageName = validatedParams.packageName + this.packageNames = validatedParams.packageNames this.numOldVersionsToDelete = validatedParams.numOldVersionsToDelete this.minVersionsToKeep = validatedParams.minVersionsToKeep this.ignoreVersions = validatedParams.ignoreVersions @@ -53,7 +57,7 @@ export class Input { return !!( this.owner && this.repo && - this.packageName && + (this.packageName || this.packageNames) && this.numOldVersionsToDelete >= 0 && this.token ) diff --git a/src/main.ts b/src/main.ts index 2905ad0e..8a88d1c1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,6 +13,7 @@ function getActionInput(): Input { owner: getInput('owner') ? getInput('owner') : context.repo.owner, repo: getInput('repo') ? getInput('repo') : context.repo.repo, packageName: getInput('package-name'), + packageNames: getInput('package-names'), numOldVersionsToDelete: Number(getInput('num-old-versions-to-delete')), minVersionsToKeep: Number(getInput('min-versions-to-keep')), ignoreVersions: RegExp(getInput('ignore-versions')), diff --git a/src/packages/get-packages.ts b/src/packages/get-packages.ts new file mode 100644 index 00000000..d714ab63 --- /dev/null +++ b/src/packages/get-packages.ts @@ -0,0 +1,165 @@ +// 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 '../common/graphql' + +export interface PackageInfo { + id: string + name: string +} + +export interface QueryInfo { + packages: PackageInfo[] + cursor: string + paginate: boolean +} + +export interface GetPackagesQueryResponse { + repository: { + packages: { + edges: {node: PackageInfo}[] + pageInfo: { + endCursor: string + hasNextPage: boolean + } + } + } +} + +const query = ` + query getPackages($owner: String!, $repo: String!, $first: Int!){ + repository(owner: $owner, name: $repo) { + packages(first:$first){ + edges { + node { + name + id + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + }` + +const Paginatequery = ` + query getPackages($owner: String!, $repo: String!, $first: Int!, $after: String!){ + repository(owner: $owner, name: $repo) { + packages(first:$first){ + edges { + node { + name + id + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + }` + +export function queryForRepoPackages( + owner: string, + repo: string, + numPackages: number, + startCursor: string, + token: string +): Observable { + if (startCursor === '') { + return from( + graphql(token, query, { + owner, + repo, + first: numPackages, + headers: { + Accept: 'application/vnd.github.packages-preview+json' + } + }) as Promise + ).pipe( + catchError((err: GraphQlQueryResponse) => { + const msg = 'query for packages failed.' + return throwError( + err.errors && err.errors.length > 0 + ? `${msg} ${err.errors[0].message}` + : `${msg} verify input parameters are correct ${JSON.stringify( + err, + null, + 2 + )}` + ) + }) + ) + } else { + return from( + graphql(token, Paginatequery, { + owner, + repo, + first: numPackages, + before: startCursor, + headers: { + Accept: 'application/vnd.github.packages-preview+json' + } + }) as Promise + ).pipe( + catchError((err: GraphQlQueryResponse) => { + const msg = 'query for packages failed.' + return throwError( + err.errors && err.errors.length > 0 + ? `${msg} ${err.errors[0].message}` + : `${msg} verify input parameters are correct` + ) + }) + ) + } +} + +export function getRepoPackages( + owner: string, + repo: string, + numPackages: number, + startCursor: string, + token: string +): Observable { + return queryForRepoPackages( + owner, + repo, + numPackages, + startCursor, + token + ).pipe( + map(result => { + let r: QueryInfo + if (result.repository.packages.edges.length < 1) { + console.log( + `package: No packages found for owner: ${owner} in repo: ${repo}` + ) + r = { + packages: [] as PackageInfo[], + cursor: '', + paginate: false + } + return r + } + + const packages = result.repository.packages.edges + const pages = result.repository.packages.pageInfo + + r = { + packages: packages.map(value => ({ + id: value.node.id, + name: value.node.name + })), + cursor: pages.endCursor, + paginate: pages.hasNextPage + } + + return r + }) + ) +} diff --git a/src/packages/index.ts b/src/packages/index.ts new file mode 100644 index 00000000..eadf04e4 --- /dev/null +++ b/src/packages/index.ts @@ -0,0 +1,2 @@ +export * from './get-packages' +export * from './package-name-filter' diff --git a/src/packages/package-name-filter.ts b/src/packages/package-name-filter.ts new file mode 100644 index 00000000..fba0af00 --- /dev/null +++ b/src/packages/package-name-filter.ts @@ -0,0 +1,126 @@ +/** + * Used to apply memoization on getPackageNameFilter + */ +const resultCache = {} as Record + +interface PackageNameSubFilter { + type: 'regex' | 'wildcard' | 'string' + apply: (packageName: string) => boolean +} + +interface PackageNamesFilter { + readonly subfilters: readonly PackageNameSubFilter[] + readonly isEmpty: boolean + readonly apply: (packageName: string) => boolean +} + +/** + * Get a filter based on package names to match + * + * @param packageNames - serialized package names filter as string + * @returns the respective package filter + */ +export function getPackageNameFilter(packageNames: string): PackageNamesFilter { + if (resultCache[packageNames]) { + return resultCache[packageNames] + } + const result = calculatePackageNameFilter(packageNames) + resultCache[packageNames] = result + return result +} + +const emptyFilter = Object.freeze({ + subfilters: Object.freeze([]), + isEmpty: true, + apply: () => false as boolean +}) + +/** + * Generates a filter based package names to match + * + * @param packageNames - serialized package names filter as string + * @returns the respective package filter + */ +function calculatePackageNameFilter( + packageNames: string +): Readonly { + if (packageNames === '') { + return emptyFilter + } + const separatedPackageNames = packageNames + .split(',') + .map(name => name.trim()) + .filter(name => name !== '') + + if (separatedPackageNames.length <= 0) { + return emptyFilter + } + + const subfilters = separatedPackageNames.map(createFilter) + return { + subfilters, + isEmpty: subfilters.length <= 0, + apply: names => subfilters.some(filter => filter.apply(names)) + } +} + +function createFilter(packageName: string): PackageNameSubFilter { + if (packageName.startsWith('*') || packageName.endsWith('*')) { + return createWildcardFilter(packageName) + } else if (packageName.startsWith('/') && packageName.endsWith('/')) { + return createRegexFilter(packageName) + } else { + return createExactMatchFilter(packageName) + } +} + +function createWildcardFilter( + wildcardPackageName: string +): PackageNameSubFilter { + const startsWithWildCard = wildcardPackageName.startsWith('*') + const endsWithWildCard = wildcardPackageName.endsWith('*') + let fn: PackageNameSubFilter['apply'] + if (wildcardPackageName === '*') { + fn = () => true + } else if (startsWithWildCard && endsWithWildCard) { + const targetText = wildcardPackageName.substring( + 1, + wildcardPackageName.length - 1 + ) + fn = (packageName: string) => packageName.includes(targetText) + } else if (startsWithWildCard) { + const targetText = wildcardPackageName.substring(1) + fn = (packageName: string) => packageName.endsWith(targetText) + } else { + const targetText = wildcardPackageName.substring( + 0, + wildcardPackageName.length - 1 + ) + fn = (packageName: string) => packageName.startsWith(targetText) + } + return { + type: 'wildcard', + apply: fn + } +} + +function createRegexFilter(regexPackageName: string): PackageNameSubFilter { + const regexPattern = regexPackageName.substring( + 1, + regexPackageName.length - 1 + ) + const regex = new RegExp(regexPattern) + return { + type: 'regex', + apply: (packageName: string) => regex.test(packageName) + } +} + +function createExactMatchFilter( + matchingPackageName: string +): PackageNameSubFilter { + return { + type: 'string', + apply: (packageName: string) => packageName === matchingPackageName + } +} diff --git a/src/version/delete-version.ts b/src/version/delete-version.ts index d528ca1b..2f247e86 100644 --- a/src/version/delete-version.ts +++ b/src/version/delete-version.ts @@ -1,7 +1,7 @@ // 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 {graphql} from './graphql' +import {graphql} from '../common/graphql' let deleted = 0 diff --git a/src/version/get-versions.ts b/src/version/get-versions.ts index c49d57eb..8a0299b0 100644 --- a/src/version/get-versions.ts +++ b/src/version/get-versions.ts @@ -3,7 +3,7 @@ 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' +import {graphql} from '../common/graphql' export interface VersionInfo { id: string