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
261 changes: 235 additions & 26 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build SimpleLogin-AIO
name: CI / SimpleLogin-AIO

on:
push:
Expand All @@ -7,18 +7,20 @@ on:
- 'Dockerfile'
- 'rootfs/**'
- 'scripts/**'
- 'simplelogin-aio.xml'
- 'upstream.toml'
- '.github/workflows/build.yml'
- 'simplelogin-aio.xml'
- 'renovate.json'
- '.github/workflows/**'
pull_request:
branches: [ main ]
paths:
- 'Dockerfile'
- 'rootfs/**'
- 'scripts/**'
- 'simplelogin-aio.xml'
- 'upstream.toml'
- '.github/workflows/build.yml'
- 'simplelogin-aio.xml'
- 'renovate.json'
- '.github/workflows/**'
workflow_dispatch:
inputs:
run_smoke_test:
Expand All @@ -42,29 +44,183 @@ concurrency:
cancel-in-progress: true

jobs:
validate:
detect-changes:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
build_related: ${{ steps.filter.outputs.build_related }}
xml_related: ${{ steps.filter.outputs.xml_related }}
renovate_related: ${{ steps.filter.outputs.renovate_related }}
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0

- name: Classify changed files
id: filter
env:
EVENT_NAME: ${{ github.event_name }}
BEFORE_SHA: ${{ github.event.before || '' }}
BASE_SHA: ${{ github.event.pull_request.base.sha || '' }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
GITHUB_SHA_VALUE: ${{ github.sha }}
run: |
if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then
echo "build_related=true" >> "${GITHUB_OUTPUT}"
echo "xml_related=true" >> "${GITHUB_OUTPUT}"
echo "renovate_related=true" >> "${GITHUB_OUTPUT}"
exit 0
fi

if [[ "${EVENT_NAME}" == "pull_request" ]]; then
base="${BASE_SHA}"
head="${HEAD_SHA}"
else
base="${BEFORE_SHA}"
head="${GITHUB_SHA_VALUE}"
fi

if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "Git metadata is unavailable; treating the workflow as fully impacted."
echo "build_related=true" >> "${GITHUB_OUTPUT}"
echo "xml_related=true" >> "${GITHUB_OUTPUT}"
echo "renovate_related=true" >> "${GITHUB_OUTPUT}"
exit 0
fi

if [[ -z "${base}" || "${base}" =~ ^0+$ ]]; then
if ! changed_files="$(git show --pretty='' --name-only "${head}" 2>/dev/null)"; then
echo "Unable to inspect commit range; treating the workflow as fully impacted."
echo "build_related=true" >> "${GITHUB_OUTPUT}"
echo "xml_related=true" >> "${GITHUB_OUTPUT}"
echo "renovate_related=true" >> "${GITHUB_OUTPUT}"
exit 0
fi
else
if ! changed_files="$(git diff --name-only "${base}" "${head}" 2>/dev/null)"; then
echo "Unable to diff commit range; treating the workflow as fully impacted."
echo "build_related=true" >> "${GITHUB_OUTPUT}"
echo "xml_related=true" >> "${GITHUB_OUTPUT}"
echo "renovate_related=true" >> "${GITHUB_OUTPUT}"
exit 0
fi
fi

printf 'Changed files:\n%s\n' "${changed_files}"

build_related=false
xml_related=false
renovate_related=false

while IFS= read -r path; do
[[ -z "${path}" ]] && continue
case "${path}" in
Dockerfile|upstream.toml|rootfs/*|scripts/*)
build_related=true
;;
simplelogin-aio.xml)
xml_related=true
;;
renovate.json)
renovate_related=true
;;
.github/workflows/*)
build_related=true
renovate_related=true
;;
esac
done <<< "${changed_files}"

echo "build_related=${build_related}" >> "${GITHUB_OUTPUT}"
echo "xml_related=${xml_related}" >> "${GITHUB_OUTPUT}"
echo "renovate_related=${renovate_related}" >> "${GITHUB_OUTPUT}"

validate-repo:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.build_related == 'true' || needs.detect-changes.outputs.xml_related == 'true' || needs.detect-changes.outputs.renovate_related == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Validate scripts and metadata
- name: Validate shell and python scripts
if: ${{ needs.detect-changes.outputs.build_related == 'true' }}
run: |
bash -n scripts/smoke-test.sh
python3 -m py_compile scripts/check-upstream.py
PYTHONPYCACHEPREFIX=/tmp/simplelogin-aio-pyc python3 -m py_compile scripts/check-upstream.py
find rootfs -type f -name '*.sh' -print0 | xargs -0 -n1 bash -n
find rootfs -type f -path '*/run' -print0 | xargs -0 -n1 bash -n

- name: Validate XML
if: ${{ needs.detect-changes.outputs.build_related == 'true' || needs.detect-changes.outputs.xml_related == 'true' }}
run: |
python3 - <<'PY'
import xml.etree.ElementTree as ET
ET.parse("simplelogin-aio.xml")
print("Parsed simplelogin-aio.xml successfully")
ET.parse('simplelogin-aio.xml')
print('simplelogin-aio.xml parsed successfully')
PY

- name: Validate Renovate config
if: ${{ needs.detect-changes.outputs.renovate_related == 'true' }}
run: npx --yes --package renovate renovate-config-validator renovate.json

pinned-actions:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Enforce pinned action SHAs
run: |
python3 - <<'PY'
import pathlib
import re
import sys

workflow_dir = pathlib.Path(".github/workflows")
pattern = re.compile(r"^\s*uses:\s*([^@\s]+)@([^\s#]+)")
sha_pattern = re.compile(r"^[0-9a-f]{40}$")
failures = []

for path in sorted(workflow_dir.glob("*.yml")):
for lineno, line in enumerate(path.read_text().splitlines(), start=1):
match = pattern.match(line)
if not match:
continue
target, ref = match.groups()
if target.startswith("./"):
continue
if not sha_pattern.fullmatch(ref):
failures.append(f"{path}:{lineno}: action is not pinned to a full SHA -> {line.strip()}")

if failures:
print("\n".join(failures), file=sys.stderr)
sys.exit(1)
print("All workflow actions are pinned to full commit SHAs.")
PY

dependency-review:
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Dependency review
uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2

smoke-test:
if: ${{ github.event_name != 'workflow_dispatch' || inputs.run_smoke_test == true }}
needs: validate
if: ${{ needs.detect-changes.outputs.build_related == 'true' && (github.event_name != 'workflow_dispatch' || inputs.run_smoke_test == true) }}
needs:
- detect-changes
- validate-repo
- pinned-actions
runs-on: ubuntu-latest
permissions:
contents: read
Expand All @@ -79,9 +235,9 @@ jobs:
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
platforms: linux/amd64
load: true
tags: simplelogin-aio:ci
platforms: linux/amd64
cache-from: type=gha
cache-to: type=gha,mode=max

Expand All @@ -99,9 +255,11 @@ jobs:
docker logs simplelogin-aio-smoke || true

publish:
if: ${{ github.event_name != 'pull_request' && ((github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && inputs.publish_image == true)) }}
if: ${{ needs.detect-changes.outputs.build_related == 'true' && github.event_name != 'pull_request' && ((github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && inputs.publish_image == true)) }}
needs:
- validate
- detect-changes
- validate-repo
- pinned-actions
- smoke-test
runs-on: ubuntu-latest
permissions:
Expand All @@ -126,30 +284,81 @@ jobs:
run: |
image="${REGISTRY}/${IMAGE_NAME}"
sha_tag="${image}:sha-${GITHUB_SHA}"
version="$(awk -F= '/^ARG UPSTREAM_VERSION=/{print $2; exit}' Dockerfile)"
version="$(sed -n 's/^ARG UPSTREAM_VERSION=//p' Dockerfile | head -n1)"
version_no_v="${version#v}"
IFS='.' read -r major minor patch <<< "${version_no_v}"

{
echo "upstream_version=${version}"
echo "tags<<EOF"
echo "${image}:latest"
echo "${image}:${version}"
if [[ -n "${major:-}" ]]; then
echo "${image}:v${major}"
fi
if [[ -n "${major:-}" && -n "${minor:-}" ]]; then
echo "${image}:v${major}.${minor}"
if [[ -n "${version}" ]]; then
IFS='.' read -r major minor patch <<< "${version_no_v}"
echo "${image}:${version}"
if [[ -n "${major:-}" ]]; then
echo "${image}:v${major}"
fi
if [[ -n "${major:-}" && -n "${minor:-}" ]]; then
echo "${image}:v${major}.${minor}"
fi
fi
echo "${sha_tag}"
echo "EOF"
} >> "${GITHUB_OUTPUT}"

- name: Build and push amd64 image
- name: Build and push
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
push: true
tags: ${{ steps.prep.outputs.tags }}
platforms: linux/amd64
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.source=https://github.com/JSONbored/simplelogin-aio
org.opencontainers.image.title=simplelogin-aio
org.opencontainers.image.version=${{ steps.prep.outputs.upstream_version || '' }}
io.jsonbored.upstream.name=SimpleLogin

sync-awesome-unraid:
if: ${{ needs.detect-changes.outputs.xml_related == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
needs:
- detect-changes
- validate-repo
- pinned-actions
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check sync configuration
env:
SYNC_TOKEN: ${{ secrets.SYNC_TOKEN }}
run: |
if [[ -z "${SYNC_TOKEN}" ]]; then
echo "SYNC_ENABLED=false" >> "${GITHUB_ENV}"
echo "SYNC_TOKEN is not configured; skipping sync."
else
echo "SYNC_ENABLED=true" >> "${GITHUB_ENV}"
fi

- name: Checkout Source Repository
if: ${{ env.SYNC_ENABLED == 'true' }}
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Checkout Target Repository
if: ${{ env.SYNC_ENABLED == 'true' }}
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
repository: JSONbored/awesome-unraid
token: ${{ secrets.SYNC_TOKEN }}
path: target-repo

- name: Copy and commit template
if: ${{ env.SYNC_ENABLED == 'true' }}
run: |
cp simplelogin-aio.xml target-repo/simplelogin-aio.xml
cd target-repo
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add simplelogin-aio.xml
git diff --quiet && git diff --staged --quiet || (git commit -m "chore: auto-sync simplelogin-aio.xml from upstream" && git push)
Loading
Loading