Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>panicboat/.github"
]
}
14 changes: 14 additions & 0 deletions .github/workflows/ci-gatekeeper.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Waits for every other workflow on a pull request so that one required check gates the merge.
name: 'CI Gatekeeper'

on:
pull_request:
types: [opened, synchronize, reopened]
branches:
- '**'

jobs:
gatekeeper:
permissions:
actions: read
uses: ./.github/workflows/reusable--ci-gatekeeper.yaml
13 changes: 13 additions & 0 deletions .github/workflows/lint-actions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Checks that every action is pinned to a full commit SHA.
name: Lint GitHub Actions

on:
push:
branches: [main]
pull_request:

jobs:
lint:
permissions:
contents: read
uses: ./.github/workflows/reusable--lint-actions.yaml
21 changes: 21 additions & 0 deletions .github/workflows/release--please.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Runs release-please for this repository to open release pull requests and publish releases.
name: 'Release - Please'

on:
push:
branches: [main]
workflow_dispatch: {}

concurrency:
group: release-please
cancel-in-progress: false

jobs:
release-please:
permissions:
contents: read
uses: ./.github/workflows/reusable--release--please.yaml
with:
app-id: ${{ vars.APP_ID }}
secrets:
private-key: ${{ secrets.APP_PRIVATE_KEY }}
23 changes: 23 additions & 0 deletions .github/workflows/reusable--ci-gatekeeper.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Waits for every other workflow on a pull request so that one required check gates the merge.
name: 'Reusable - CI Gatekeeper'

on:
workflow_call:
inputs:
exclude-workflow-names:
required: false
type: string
default: ''
description: 'Workflow names the gatekeeper does not wait for, one per line'

jobs:
ci-gatekeeper:
name: CI Gatekeeper
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Wait for other workflows
uses: int128/wait-for-workflows-action@b320164b37276db89a12829914d6eb6ef4973d2b # v1.108.0
with:
max-timeout-seconds: 1800
exclude-workflow-names: ${{ inputs.exclude-workflow-names }}
70 changes: 70 additions & 0 deletions .github/workflows/reusable--cleanup-container-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Deletes stale pr- and sha- tags and untagged images of the given service containers in ghcr.io.
name: 'Reusable - Cleanup Container Images'

on:
workflow_call:
inputs:
services:
required: true
type: string
description: 'JSON array of service names whose containers are cleaned (e.g. ["monolith","frontend"])'

jobs:
cleanup-container:
name: 'Cleanup ${{ matrix.service }}'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
service: ${{ fromJson(inputs.services) }}
fail-fast: false
steps:
- name: Clean old PR tags
uses: dataaxiom/ghcr-cleanup-action@d52806a0dc70b430571a37da1fde39733ffd640f # v1.2.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
package: ${{ github.event.repository.name }}/${{ matrix.service }}
delete-tags: ^pr-
older-than: 1 days
exclude-tags: ^(latest|v\d+\.\d+\.\d+.*)$
use-regex: true
validate: true

- name: Clean SHA tags
uses: dataaxiom/ghcr-cleanup-action@d52806a0dc70b430571a37da1fde39733ffd640f # v1.2.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
package: ${{ github.event.repository.name }}/${{ matrix.service }}
delete-tags: ^sha-
exclude-tags: ^(latest|v\d+\.\d+\.\d+.*)$
use-regex: true
validate: true

- name: Clean untagged images
uses: dataaxiom/ghcr-cleanup-action@d52806a0dc70b430571a37da1fde39733ffd640f # v1.2.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
package: ${{ github.event.repository.name }}/${{ matrix.service }}
keep-n-untagged: 0
delete-orphaned-images: true
delete-ghost-images: true
delete-partial-images: true
exclude-tags: ^(latest|v\d+\.\d+\.\d+.*)$
use-regex: true
validate: true

summary:
name: 'Cleanup Summary'
needs: cleanup-container
if: always()
runs-on: ubuntu-latest
steps:
- name: Summary
env:
SERVICES: ${{ inputs.services }}
run: |
echo "📊 Cleanup Summary"
echo "Services: ${SERVICES}"
echo "Cleanup job status: ${{ needs.cleanup-container.result }}"
93 changes: 93 additions & 0 deletions .github/workflows/reusable--container-builder.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Builds the container image of one service and pushes it to ghcr.io.
name: Reusable Container Builder

on:
workflow_call:
inputs:
image-name:
required: true
type: string
description: 'Name of the image (e.g. service-name)'
working-directory:
required: true
type: string
description: 'Directory containing the Dockerfile'
app-id:
required: true
type: string
description: 'GitHub App ID for authentication'
semver-tag:
required: false
type: string
default: ''
description: 'Optional semver tag (e.g. v0.1.0) to add to the built image. Only set when called from release event flow.'
secrets:
private-key:
required: true
description: 'GitHub App private key for authentication'

jobs:
build-and-push:
if: inputs.image-name != ''
runs-on: ubuntu-26.04-arm

steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
app-id: ${{ inputs.app-id }}
private-key: ${{ secrets.private-key }}
owner: ${{ github.repository_owner }}

- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Check for Dockerfile
id: dockerfile
run: |
if [ -f "${{ inputs.working-directory }}/Dockerfile" ]; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Log in to the Container registry
if: steps.dockerfile.outputs.exists == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
if: steps.dockerfile.outputs.exists == 'true'
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1

- name: Extract metadata (tags, labels) for Docker
id: meta
if: steps.dockerfile.outputs.exists == 'true'
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: ghcr.io/${{ github.repository }}/${{ inputs.image-name }}
tags: |
type=sha
type=ref,event=pr
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=${{ github.actor }}
type=semver,pattern={{raw}},value=${{ inputs.semver-tag }},enable=${{ inputs.semver-tag != '' }}

- name: Build and push Docker image
if: steps.dockerfile.outputs.exists == 'true'
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
platforms: linux/arm64
context: ${{ inputs.working-directory }}
file: ${{ inputs.working-directory }}/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
Loading
Loading