-
Notifications
You must be signed in to change notification settings - Fork 0
Add github cleanup actions #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nmlinaric
wants to merge
31
commits into
master
Choose a base branch
from
feature/add-cleanup-actions
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 26 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
932573d
Add github cleanup action
nmlinaric 35694e8
Update descriptions
nmlinaric 668c190
Update test action
nmlinaric b08361f
Fix action level
nmlinaric 2ada068
Fix indentation
nmlinaric 5f428d3
Fix indentation
nmlinaric 681814c
Try to run action
nmlinaric 60eec8d
Another try
nmlinaric b141791
Another try
nmlinaric 91dc4d1
fix test ci
mpetrunic 301ff59
fix image name
mpetrunic fa70d25
fix image not pulling
mpetrunic 2516d45
Don't require excluded versions
nmlinaric 06c8d38
Use double quotes
nmlinaric 4a3c46e
Use node v12
nmlinaric 48f7eeb
Install dependecies and add build step in test
nmlinaric 5e3d463
Fix required params
nmlinaric 13d1bbf
Pipe deleted packages to logger
nmlinaric 9594045
Log deteled packages
nmlinaric e17febc
Add postgres image to test
nmlinaric 6356625
Fix typos
nmlinaric d337831
Call main function
nmlinaric 45c73db
Add gitignore
nmlinaric a3e58e9
Remove branch from test
nmlinaric d749c0b
Remove second image from test
nmlinaric f455847
Wrap main func with try-catch
nmlinaric 63ada88
Pass ogranization input to test workflow
nmlinaric b4db41d
Use PAT for auth
nmlinaric 4ecbddd
Fix organisation name
nmlinaric e18418b
Fix package filtering
nmlinaric fbf50ff
Fix filtering + passing data to action
nmlinaric File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
name: Test action | ||
|
||
on: | ||
push: | ||
branches: | ||
- 'master' | ||
pull_request: | ||
branches: | ||
- 'master' | ||
|
||
jobs: | ||
test: | ||
name: Test GitHub action | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
- name: Login to Docker Hub | ||
uses: docker/login-action@v1 | ||
with: | ||
username: ${{ github.repository_owner }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
registry: ghcr.io | ||
- name: Install dependencies | ||
run: yarn install | ||
- name: Build | ||
run: yarn run build | ||
- name: tag hello world image | ||
run: docker pull hello-world:latest && docker tag hello-world:latest ghcr.io/nodefactoryio/github-packages-cleanup-sample:${{github.sha}} | ||
- name: push hello world image | ||
run: docker push ghcr.io/nodefactoryio/github-packages-cleanup-sample:${{github.sha}} | ||
- name: Run cleanup action | ||
uses: ./ | ||
id: deleted-packages | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
package_name: github-packages-cleanup-sample | ||
num_versions_to_keep: 1 | ||
nmlinaric marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- name: Log deleted packages | ||
run: echo "Deleted packages ${{ steps.deleted-packages.outputs.DELETED_PACKAGES }}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
node_modules/ | ||
dist/ | ||
.idea | ||
.env | ||
.nyc_output | ||
lib |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
# GitHub packages cleanup | ||
|
||
GitHub action for deleting versions of a package from [GitHub Packages](https://github.com/features/packages). | ||
GitHub action for ghcr images cleanup from [GitHub Packages](https://github.com/features/packages). | ||
|
||
## Things that can be done | ||
* Delete a single version | ||
* Delete multiple versions | ||
* Delete oldest version(s) | ||
* Delete packages owned by an user or organisation | ||
* Delete packages owned by an user or organization | ||
* 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: "github ghcr images cleanup" | ||
author: "NodeFactory" | ||
description: "github ghcr images cleanup from the github package registry" | ||
inputs: | ||
excluded_versions: | ||
description: "allows to exclude certain versions, eg. x.y.z, stable, beta, latest,..." | ||
required: false | ||
num_versions_to_keep: | ||
description: "number of most recent versions to keep (excluded versions aren't included into count" | ||
required: true | ||
package_name: | ||
description: "name of github package" | ||
required: true | ||
token: | ||
description: "github auth token" | ||
required: true | ||
username: | ||
description: "github username" | ||
required: false | ||
organization: | ||
description: "github organization" | ||
required: false | ||
runs: | ||
using: "node12" | ||
main: "dist/index.js" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "github-packages-cleanup", | ||
"version": "1.0.0", | ||
"description": "TypeScript github action for ghcr images cleanup", | ||
"main": "dist/index.js", | ||
"author": { | ||
"name": "NodeFactory", | ||
"email": "[email protected]" | ||
}, | ||
"license": "MIT", | ||
"private": false, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://[email protected]:nodefactoryio/github-packages-cleanup.git" | ||
}, | ||
"scripts": { | ||
"build": "ncc build src/index.ts" | ||
}, | ||
"dependencies": { | ||
"@actions/core": "^1.2.7", | ||
"@actions/github": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^15.0.2", | ||
"@vercel/ncc": "^0.28.5", | ||
"typescript": "^4.2.4" | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { getInput, setFailed, setOutput } from "@actions/core"; | ||
import { getOctokit } from "@actions/github"; | ||
import { OctokitResponse } from "@octokit/types" | ||
import { FetchPackagesResponse } from "./types"; | ||
|
||
const excludedVersion = getInput('excluded_versions', { required: false }); | ||
const numberOfVersionsToKeep = Number(getInput('num_versions_to_keep', { required: true })); | ||
const packageName = getInput('package_name', { required: true }); | ||
const token = getInput('token', { required: true }); | ||
const username = getInput('username', { required: false }); | ||
const organization = getInput('organization', { required: false }); | ||
|
||
|
||
const octokit = getOctokit(token); | ||
|
||
async function main() { | ||
try { | ||
// delete packages with token auth | ||
if (token && !username && !organization) { | ||
const fetchedPackages = await getAuthUserPackageVersions(); | ||
const packagesToDelete = filterOutPackages(fetchedPackages); | ||
packagesToDelete.forEach(async (element) => { | ||
const output = await deleteAuthUserPackageVersions(element!.id); | ||
setOutput('DELETED_PACKAGES', output); | ||
}); | ||
// delete user packages | ||
} else if (token && username && !organization) { | ||
const fetchedPackages = await getUserPackageVersions(); | ||
const packagesToDelete = filterOutPackages(fetchedPackages); | ||
packagesToDelete.forEach(async (element) => { | ||
const output = await deleteUserPackageVersions(element!.id); | ||
setOutput('DELETED_PACKAGES', output); | ||
}); | ||
// delete organization packages | ||
} else if (token && !username && organization) { | ||
const fetchedPackages = await getOrganizationPackageVersions(); | ||
const packagesToDelete = filterOutPackages(fetchedPackages); | ||
packagesToDelete.forEach(async (element) => { | ||
const output = await deleteOrganizationPackageVersions(element!.id); | ||
setOutput('DELETED_PACKAGES', output); | ||
}); | ||
} else { | ||
setFailed("Failed to fetch packages"); | ||
} | ||
} catch (e) { | ||
console.error(`Deleting package failed because of: ${e}`); | ||
} | ||
} | ||
|
||
async function getAuthUserPackageVersions(): Promise<OctokitResponse<FetchPackagesResponse[], number>> { | ||
return await octokit.request('GET /user/packages/{package_type}/{package_name}/versions', { | ||
package_type: 'container', | ||
package_name: packageName, | ||
}); | ||
} | ||
|
||
async function deleteAuthUserPackageVersions(packageId: number): Promise<OctokitResponse<FetchPackagesResponse[], number>> { | ||
return await octokit.request('DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}', { | ||
package_type: 'container', | ||
package_name: packageName, | ||
package_version_id: packageId | ||
}); | ||
} | ||
|
||
async function getUserPackageVersions(): Promise<OctokitResponse<FetchPackagesResponse[], number>> { | ||
return await octokit.request('GET /users/{username}/packages/{package_type}/{package_name}/versions', { | ||
package_type: 'container', | ||
package_name: packageName, | ||
username: username | ||
}); | ||
} | ||
|
||
async function deleteUserPackageVersions(packageId: number): Promise<OctokitResponse<FetchPackagesResponse[], number>> { | ||
return await octokit.request('DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}', { | ||
package_type: 'container', | ||
package_name: packageName, | ||
username: username, | ||
package_version_id: packageId | ||
}); | ||
} | ||
|
||
async function getOrganizationPackageVersions(): Promise<OctokitResponse<FetchPackagesResponse[], number>> { | ||
return await octokit.request('GET /orgs/{org}/packages/{package_type}/{package_name}/versions', { | ||
package_type: 'container', | ||
package_name: packageName, | ||
org: organization | ||
}); | ||
} | ||
|
||
async function deleteOrganizationPackageVersions(packageId: number): Promise<OctokitResponse<FetchPackagesResponse[], number>> { | ||
return await octokit.request('DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}', { | ||
package_type: 'container', | ||
package_name: packageName, | ||
org: organization, | ||
package_version_id: packageId | ||
}); | ||
} | ||
|
||
function filterOutPackages(existingPackages: OctokitResponse<FetchPackagesResponse[], number>): (FetchPackagesResponse | undefined)[] { | ||
return existingPackages.data.map((item) => { | ||
// find package versions matching regex | ||
if (!item.metadata?.container?.tags[0]?.match(excludedVersion)) { | ||
return item; | ||
}; | ||
}) | ||
// filter out undefined values | ||
.filter(item => item) | ||
// packages for deletion - omitting last n values | ||
.slice(0, length - numberOfVersionsToKeep); | ||
} | ||
|
||
main(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export type PackageType = "npm" | "docker" | "container" | "maven" | "rubygems" | "nuget"; | ||
|
||
export type FetchPackagesResponse = { | ||
id: number; | ||
name: string; | ||
url: string; | ||
package_html_url?: string; | ||
html_url?: string; | ||
license?: string; | ||
description?: string; | ||
created_at: string; | ||
updated_at: string; | ||
deleted_at?: string; | ||
metadata?: { | ||
package_type: PackageType; | ||
container?: { | ||
tags: Array<any> | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "es6", | ||
"module": "commonjs", | ||
"sourceMap": true, | ||
"moduleResolution": "node", | ||
"allowSyntheticDefaultImports": true, | ||
"experimentalDecorators": true, | ||
"esModuleInterop": true, | ||
"emitDecoratorMetadata": true, | ||
"strict": true, | ||
"noImplicitAny": true, | ||
"resolveJsonModule": true, | ||
"typeRoots": [ | ||
"./node_modules/@types", | ||
"./@types" | ||
] | ||
}, | ||
"ts-node": { | ||
"transpileOnly": true, | ||
"files": true | ||
}, | ||
"include": [ | ||
"src/**/*.ts", | ||
], | ||
"exclude": [ | ||
"node_modules" | ||
] | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.