Skip to content

Commit

Permalink
feat: Add use-github-token as action input
Browse files Browse the repository at this point in the history
This commit adds the ability to use the built-in GITHUB_TOKEN secret as
passed into the GitHub Actions runner instead of providing a personal
access token (PAT) as a secret into the action for image deletion for a
package that lives in the same repository as the GitHub repository.

In order to do so, `image-name` needs to match the package name for the
repository from where this action is being invoked.
  • Loading branch information
Injabie3 authored and sondrelg committed Dec 7, 2023
1 parent 3d27e6a commit cbce1ab
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
9 changes: 8 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ inputs:
description: "Do not actually delete images. Print output showing what would have been deleted."
required: false
default: 'false'
use-github-token:
description: "Whether the supplied token is GITHUB_TOKEN. If true, image-names must the package name of repository from where this action is invoked."
required: false
default: 'false'

outputs:
needs-github-assistance:
description: 'Comma-separated list of image names and tags, for image versions that are public and have more than 5000 downloads.'
Expand Down Expand Up @@ -89,7 +94,8 @@ runs:
"$KEEP_AT_LEAST" \
"$FILTER_TAGS" \
"$FILTER_INCLUDE_UNTAGGED" \
"$DRY_RUN"
"$DRY_RUN" \
"$USE_GITHUB_TOKEN"
env:
ACCOUNT_TYPE: "${{ inputs.account-type }}"
ORG_NAME: "${{ inputs.org-name }}"
Expand All @@ -103,3 +109,4 @@ runs:
FILTER_TAGS: "${{ inputs.filter-tags }}"
FILTER_INCLUDE_UNTAGGED: "${{ inputs.filter-include-untagged }}"
DRY_RUN: "${{ inputs.dry-run }}"
USE_GITHUB_TOKEN: "${{ inputs.use-github-token }}"
38 changes: 31 additions & 7 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ async def delete_package(


class Inputs(BaseModel):
use_github_token: bool = False
image_names: list[str]
cut_off: datetime
timestamp_to_use: TimestampType
Expand All @@ -335,10 +336,23 @@ class Inputs(BaseModel):
filter_include_untagged: bool = True
dry_run: bool = False

@field_validator('skip_tags', 'filter_tags', 'image_names', mode='before')
def parse_comma_separate_string_as_list(cls, v: str) -> list[str]:
@staticmethod
def _parse_comma_separate_string_as_list(v: str) -> list[str]:
return [i.strip() for i in v.split(',')] if v else []

@field_validator('skip_tags', 'filter_tags', mode='before')
def parse_comma_separate_string_as_list(cls, v: str) -> list[str]:
return cls._parse_comma_separate_string_as_list(v)

@field_validator('image_names', mode='before')
def validate_image_names(cls, v: str, values: dict) -> list[str]:
images = cls._parse_comma_separate_string_as_list(v)
if values.data['use_github_token'] and len(images) != 1:
raise ValueError('A single image name is required if use_github_token is set')
if values.data['use_github_token'] and '*' in images[0]:
raise ValueError('A single image name is required if use_github_token is set')
return images

@field_validator('cut_off', mode='before')
def parse_human_readable_datetime(cls, v: str) -> datetime:
parsed_cutoff = parse(v)
Expand Down Expand Up @@ -510,6 +524,7 @@ async def main(
filter_tags: str,
filter_include_untagged: str,
dry_run: str = 'false',
use_github_token: str = 'false',
) -> None:
"""
Delete old image versions.
Expand Down Expand Up @@ -538,6 +553,9 @@ async def main(
:param filter_include_untagged: Whether to consider untagged images for deletion.
:param dry_run: Do not actually delete packages but print output showing which packages would
have been deleted.
:param use_github_token: Whether token is using GITHUB_TOKEN. Requires a single image in
image_names, and the image matches the package name from the
repository where this action is invoked.
"""
inputs = Inputs(
image_names=image_names,
Expand All @@ -551,17 +569,23 @@ async def main(
filter_tags=filter_tags,
filter_include_untagged=filter_include_untagged,
dry_run=dry_run,
use_github_token=use_github_token,
)
async with AsyncClient(
headers={'accept': 'application/vnd.github.v3+json', 'Authorization': f'Bearer {token}'}
) as client:
# Get all packages from the user or orgs account
all_packages = await GithubAPI.list_packages(
account_type=inputs.account_type, org_name=inputs.org_name, http_client=client
)
if inputs.use_github_token:
packages_to_delete_from = set(inputs.image_names)
else:
all_packages = await GithubAPI.list_packages(
account_type=inputs.account_type,
org_name=inputs.org_name,
http_client=client,
)

# Filter existing image names by action inputs
packages_to_delete_from = filter_image_names(all_packages, inputs.image_names)
# Filter existing image names by action inputs
packages_to_delete_from = filter_image_names(all_packages, inputs.image_names)

# Create tasks to run concurrently
tasks = [
Expand Down

0 comments on commit cbce1ab

Please sign in to comment.