Skip to content

Commit

Permalink
feat: init
Browse files Browse the repository at this point in the history
  • Loading branch information
WoozyMasta committed Feb 21, 2022
0 parents commit f5dbd24
Show file tree
Hide file tree
Showing 13 changed files with 526 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.vscode/
.venv/
.git/
extras
.env
.env.example
.gitignore
README.md
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
QUAY_URL=https://quay.local.tld
QUAY_TOKEN=
# QUAY_DRY_RUN=False
# QUAY_IMAGE_EXPIRE=336h
77 changes: 77 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Create Release
on:
push:
tags:
- "*.**.**"

jobs:
push_to_registries:
name: Push Docker image to multiple registries
runs-on: ubuntu-latest
permissions:
packages: write
contents: write
steps:
- name: Check out the repo
uses: actions/checkout@v2

- name: Log in to Docker Hub Container registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Log in to Quay Container registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
registry: quay.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Log in to GitHub Container registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: |
${{ github.repository }}
quay.io/${{ github.repository }}
ghcr.io/${{ github.repository }}
- name: Build and push Docker images
uses: docker/build-push-action@v2
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

- name: Set env
id: env
run: |
echo ::set-output name=PROJECT_NAME::${GITHUB_REF#refs/*/}
echo ::set-output name=PROJECT_BRANCH::${GITHUB_REF#refs/heads/}
echo ::set-output name=PROJECT_TAG::${GITHUB_REF#refs/tags/}
- name: Create Release
id: create_release
uses: ncipollo/release-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
body: |
## Container images
* `docker pull ghcr.io/woozymasta/quay-expiration:${{ steps.env.outputs.PROJECT_TAG }}`
* `docker pull quay.io/woozymasta/quay-expiration:${{ steps.env.outputs.PROJECT_TAG }}`
* `docker pull docker.io/woozymasta/quay-expiration:${{ steps.env.outputs.PROJECT_TAG }}`
draft: false
prerelease: false
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.venv/
.env
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"ms-python.python",
"redhat.vscode-yaml",
"exiasr.hadolint",
"davidanson.vscode-markdownlint"
]
}
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"python.pythonPath": ".venv/bin/python",
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/.venv": true,
},
}
39 changes: 39 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Define base images and tags
# ---------------------------
ARG DOCKERFILE_BUILD_IMAGE="docker.io/python"
ARG DOCKERFILE_BUILD_TAG="3.10-slim-bullseye"
ARG DOCKERFILE_BASE_IMAGE="docker.io/python"
ARG DOCKERFILE_BASE_TAG="3.10-alpine3.15"

# Build env
# ---------
FROM $DOCKERFILE_BUILD_IMAGE:$DOCKERFILE_BUILD_TAG as build

ARG PIP_INDEX_URL=https://pypi.org/simple/
ARG PIP_INDEX=https://pypi.org/pypi/

# hadolint ignore=DL3013
RUN set -eux && \
pip install --no-cache-dir --upgrade wheel

ENV PATH "/app/.venv/bin:$PATH"

WORKDIR /app

COPY requirements.txt ./

RUN set -eux && \
python -m venv .venv && \
pip install --no-cache-dir --upgrade --requirement requirements.txt && \
rm -f requirements.txt

# Create quay expiration image
# ----------------------
FROM $DOCKERFILE_BASE_IMAGE:$DOCKERFILE_BASE_TAG

WORKDIR /app
COPY --from=build /app/.venv /app/.venv
COPY expiration.py config.yml ./
ENV PATH "/app/.venv/bin:$PATH"

ENTRYPOINT ["/app/expiration.py"]
98 changes: 98 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Quay Image Expiration

Python script to change the image lifetime in the [Quay][] container registry.
Allows you to set different lifetimes for different tags according to a regular
expression. Will not change existing TTL labels.

![demo](extras/quay-expiration.gif)

Add this script to your scheduler (crontab, systemd timer, kubernetes cronJo
or similar) and keep your container registry clean. No more junk tags,
intermediate versions live for a limited time, only releases stay forever.

> Quay has support for the `quay.expires-after` label which allows you to set
> the lifetime of an artifact at the build stage in your CI pipeline.
> But not all good fellows use it, that's why this script appeared, for total
> control over the lifetime of images.
## Configuration

* **`QUAY_URL`** - URL of Quay instance.
Takes precedence over YAML configuration key `quay.url` and it's the same.
* **`QUAY_TOKEN`** - Token with owner or admin permissions for change
expiration.
Takes precedence over YAML configuration key `quay.token` and it's the same.
* **`QUAY_DRY_RUN`**=`False` - Test run script for review,
will not change anything.
Takes precedence over YAML configuration key `quay.dry_run` and it's the same.
* **`QUAY_IMAGE_EXPIRE`**=`336h` - Default image expiration time.
Takes precedence over YAML configuration key `quay.default_expiration`
and it's the same.

Default config stored in [`config.yml`](config.yml)

```yml
quay:
url: # URL of Quay instance
token: # Token with owner or admin permissions for change expiration
dry_run: false # Test run script for review, will not change anything.
exclude_projects: # List of ignored projects
- group/project
default_expiration: 336h # Default image expiration time.
expiration: # Regex rules for tags and expiration time for matches
- name: release
regex: ^(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2}$
expire: 0s
- name: double release
regex: ^(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2}(-(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2})$
expire: 0s
- name: latest
regex: ^latest((\+|-)[0-9A-Za-z\.-]+){0,2}$
expire: 0s
- name: meta release
regex: ^(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2}((\+|-)[0-9A-Za-z\.-]+){1,3}$
expire: 336h
- name: development
regex: ^(dev(el(op(ment)?)?)?|[0-9a-zA-Z-]*-rc)$
expire: 192h

```

## Exclude projects

Whatever the lifetime of the project/tag is not changed:

* The tag must already have a lifetime, by setting 999 years you explicitly
tell it to live long, long enough I guess.
* The tag must match the regular expression where the time is set to
`expire: 0s` - this means the tag will not disappear.
* Add projects to the `exclude_projects` list of the configuration and they
will be skipped in the analysis.

## Container Image

* [`docker pull ghcr.io/woozymasta/quay-expiration:latest`](https://github.com/WoozyMasta/quay-expirationp/pkgs/container/quay-expiration)
* [`docker pull quay.io/woozymasta/quay-expiration:latest`](https://quay.io/repository/woozymasta/quay-expiration)
* [`docker pull docker.io/woozymasta/quay-expiration:latest`](https://hub.docker.com/r/woozymasta/quay-expiration)

```bash
docker run --rm -ti \
-e "QUAY_URL=https://quay.tld.local" \
-e "QUAY_TOKEN=XXXXXXXX" \
-e "QUAY_DRY_RUN=true" \
-v "$(pwd):/app/config.yml" \
ghcr.io/woozymasta/quay-expiration:latest
```

## Running code locally from a repo

```bash
python -m venv .venv
. ./.venv/bin/activate
cp .env.example .env
editor .env
editor config.yml
./expiration.py
```

[Quay]: https://www.projectquay.io
24 changes: 24 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
quay:
url:
token:
dry_run: false
exclude_projects:
- group/project
default_expiration: 336h
expiration:
- name: release
regex: ^(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2}$
expire: 0s
- name: double release
regex: ^(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2}(-(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2})$
expire: 0s
- name: latest
regex: ^latest((\+|-)[0-9A-Za-z\.-]+){0,2}$
expire: 0s
- name: meta release
regex: ^(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*)){2}((\+|-)[0-9A-Za-z\.-]+){1,3}$
expire: 336h
- name: development
regex: ^(dev(el(op(ment)?)?)?|[0-9a-zA-Z-]*-rc)$
expire: 192h
Loading

0 comments on commit f5dbd24

Please sign in to comment.