diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml new file mode 100644 index 0000000..dbc55cc --- /dev/null +++ b/.gitea/workflows/ci.yaml @@ -0,0 +1,214 @@ +name: ci + +on: + push: + branches: + - "**" + pull_request: + workflow_dispatch: + +env: + REGISTRY: gcr.forust.xyz + +jobs: + lint: + runs-on: [self-hosted, linux, arch, homelab] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check formatting with Prettier + shell: bash + run: | + mapfile -t prettier_files < <( + git ls-files \ + | grep -E '\.(md|json|ya?ml|html|css)$' \ + | grep -Ev '^(\.docs/|\.zed/|errorpages/html/|homepages/(forust_files|xdfnx_files)/)' + ) + + if [ "${#prettier_files[@]}" -eq 0 ]; then + echo "No Prettier-managed files found." + exit 0 + fi + + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + node:22-alpine \ + sh -lc 'npx --yes prettier@3 --check --ignore-unknown "$@"' sh "${prettier_files[@]}" + + - name: Lint Python with Ruff + shell: bash + run: | + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + ghcr.io/astral-sh/ruff:latest \ + check . + + - name: Lint YAML syntax + shell: bash + run: | + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + cytopia/yamllint:latest \ + -c .yamllint . + + - name: Lint Dockerfiles + shell: bash + run: | + mapfile -t dockerfiles < <( + git ls-files ':(glob)**/Dockerfile' ':(glob)**/Dockerfile.*' + ) + + if [ "${#dockerfiles[@]}" -eq 0 ]; then + echo "No Dockerfiles found." + exit 0 + fi + + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + --entrypoint hadolint \ + hadolint/hadolint:latest-debian \ + -c .hadolint.yaml "${dockerfiles[@]}" + + validate: + runs-on: [self-hosted, linux, arch, homelab] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate YAML syntax + shell: bash + run: | + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + cytopia/yamllint:latest \ + -c .yamllint . + + - name: Validate Kubernetes manifests + shell: bash + run: | + mapfile -t manifests < <( + git ls-files ':(glob)**/k8s/**/*.yaml' ':(glob)**/k8s/**/*.yml' \ + | grep -Ev '(^|/)(kustomization\.ya?ml|.*\.example\.ya?ml|.*values\.ya?ml|patch-.*\.ya?ml)$' + ) + + if [ "${#manifests[@]}" -eq 0 ]; then + echo "No Kubernetes manifests found." + exit 0 + fi + + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + ghcr.io/yannh/kubeconform:latest \ + -strict \ + -ignore-missing-schemas \ + -summary \ + "${manifests[@]}" + + build: + if: github.event_name != 'pull_request' && github.ref_name == 'main' + runs-on: [self-hosted, linux, arch, homelab] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Detect changed docker-built services + id: services + shell: bash + run: | + base="${{ github.event.before }}" + if [ -z "$base" ] || [ "$base" = "0000000000000000000000000000000000000000" ]; then + base="$(git rev-list --max-parents=0 HEAD)" + fi + + mapfile -t changed_files < <(git diff --name-only "$base" "${GITHUB_SHA}") + + services=() + + add_service() { + local name="$1" + local seen=0 + for existing in "${services[@]}"; do + if [ "$existing" = "$name" ]; then + seen=1 + break + fi + done + if [ "$seen" -eq 0 ]; then + services+=("$name") + fi + } + + for file in "${changed_files[@]}"; do + case "$file" in + dtek_notif/*) + add_service dtek_notif + ;; + errorpages/*) + add_service errorpages + ;; + userbot/*) + add_service userbot + ;; + homepages/*) + add_service homepages + ;; + edu_master/phpsessid-bot/*|edu_master/webinar-checker/*|edu_master/compose.yaml) + add_service edu_master + ;; + esac + done + + if [ "${#services[@]}" -eq 0 ]; then + echo "No docker-built services changed." + echo "services=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + printf '%s\n' "${services[@]}" | tee /tmp/services.txt + echo "services=$(paste -sd, /tmp/services.txt)" >> "$GITHUB_OUTPUT" + + - name: Log in to registry + if: steps.services.outputs.services != '' + shell: bash + run: | + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "${REGISTRY}" \ + -u "${{ secrets.REGISTRY_USERNAME }}" \ + --password-stdin + + - name: Build and push changed images + if: steps.services.outputs.services != '' + shell: bash + run: | + IFS=, read -r -a services <<< "${{ steps.services.outputs.services }}" + + for service in "${services[@]}"; do + case "$service" in + dtek_notif) + docker build -t "${REGISTRY}/forust/dtek-notif:latest" dtek_notif + docker push "${REGISTRY}/forust/dtek-notif:latest" + ;; + errorpages) + docker compose -f errorpages/compose.yaml build errorpage + docker compose -f errorpages/compose.yaml push errorpage + ;; + userbot) + docker compose -f userbot/compose.yaml build forust + docker compose -f userbot/compose.yaml push forust + ;; + homepages) + docker compose -f homepages/compose.yaml build forust xdfnx + docker compose -f homepages/compose.yaml push forust xdfnx + ;; + edu_master) + docker compose -f edu_master/compose.yaml build session-keeper webinar-checker + docker compose -f edu_master/compose.yaml push session-keeper webinar-checker + ;; + esac + done diff --git a/.gitea/workflows/lint.yaml b/.gitea/workflows/lint.yaml deleted file mode 100644 index 3b8e336..0000000 --- a/.gitea/workflows/lint.yaml +++ /dev/null @@ -1,90 +0,0 @@ -name: lint - -on: - push: - branches: - - "**" - pull_request: - workflow_dispatch: - -jobs: - prettier: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Check formatting with Prettier - shell: bash - run: | - mapfile -t prettier_files < <( - git ls-files \ - | grep -E '\.(md|json|ya?ml|html|css)$' \ - | grep -Ev '^(\.docs/|\.zed/|errorpages/html/|homepages/(forust_files|xdfnx_files)/)' - ) - - if [ "${#prettier_files[@]}" -eq 0 ]; then - echo "No Prettier-managed files found." - exit 0 - fi - - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - node:22-alpine \ - sh -lc 'npx --yes prettier@3 --check --ignore-unknown "$@"' sh "${prettier_files[@]}" - - ruff: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint Python with Ruff - shell: bash - run: | - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - ghcr.io/astral-sh/ruff:latest \ - check . - - yamllint: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint YAML syntax - shell: bash - run: | - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - cytopia/yamllint:latest \ - -c .yamllint . - - hadolint: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint Dockerfiles - shell: bash - run: | - mapfile -t dockerfiles < <( - git ls-files ':(glob)**/Dockerfile' ':(glob)**/Dockerfile.*' - ) - - if [ "${#dockerfiles[@]}" -eq 0 ]; then - echo "No Dockerfiles found." - exit 0 - fi - - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - --entrypoint hadolint \ - hadolint/hadolint:latest-debian \ - -c .hadolint.yaml "${dockerfiles[@]}" diff --git a/.gitea/workflows/validate.yaml b/.gitea/workflows/validate.yaml deleted file mode 100644 index f29dddd..0000000 --- a/.gitea/workflows/validate.yaml +++ /dev/null @@ -1,52 +0,0 @@ -name: validate - -on: - push: - branches: - - "**" - pull_request: - workflow_dispatch: - -jobs: - yaml: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint YAML syntax - shell: bash - run: | - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - cytopia/yamllint:latest \ - -c .yamllint . - - k8s: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Validate Kubernetes manifests - shell: bash - run: | - mapfile -t manifests < <( - git ls-files ':(glob)**/k8s/**/*.yaml' ':(glob)**/k8s/**/*.yml' \ - | grep -Ev '(^|/)(kustomization\.ya?ml|.*\.example\.ya?ml|.*values\.ya?ml|patch-.*\.ya?ml)$' - ) - - if [ "${#manifests[@]}" -eq 0 ]; then - echo "No Kubernetes manifests found." - exit 0 - fi - - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - ghcr.io/yannh/kubeconform:latest \ - -strict \ - -ignore-missing-schemas \ - -summary \ - "${manifests[@]}" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..dbc55cc --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,214 @@ +name: ci + +on: + push: + branches: + - "**" + pull_request: + workflow_dispatch: + +env: + REGISTRY: gcr.forust.xyz + +jobs: + lint: + runs-on: [self-hosted, linux, arch, homelab] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check formatting with Prettier + shell: bash + run: | + mapfile -t prettier_files < <( + git ls-files \ + | grep -E '\.(md|json|ya?ml|html|css)$' \ + | grep -Ev '^(\.docs/|\.zed/|errorpages/html/|homepages/(forust_files|xdfnx_files)/)' + ) + + if [ "${#prettier_files[@]}" -eq 0 ]; then + echo "No Prettier-managed files found." + exit 0 + fi + + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + node:22-alpine \ + sh -lc 'npx --yes prettier@3 --check --ignore-unknown "$@"' sh "${prettier_files[@]}" + + - name: Lint Python with Ruff + shell: bash + run: | + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + ghcr.io/astral-sh/ruff:latest \ + check . + + - name: Lint YAML syntax + shell: bash + run: | + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + cytopia/yamllint:latest \ + -c .yamllint . + + - name: Lint Dockerfiles + shell: bash + run: | + mapfile -t dockerfiles < <( + git ls-files ':(glob)**/Dockerfile' ':(glob)**/Dockerfile.*' + ) + + if [ "${#dockerfiles[@]}" -eq 0 ]; then + echo "No Dockerfiles found." + exit 0 + fi + + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + --entrypoint hadolint \ + hadolint/hadolint:latest-debian \ + -c .hadolint.yaml "${dockerfiles[@]}" + + validate: + runs-on: [self-hosted, linux, arch, homelab] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate YAML syntax + shell: bash + run: | + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + cytopia/yamllint:latest \ + -c .yamllint . + + - name: Validate Kubernetes manifests + shell: bash + run: | + mapfile -t manifests < <( + git ls-files ':(glob)**/k8s/**/*.yaml' ':(glob)**/k8s/**/*.yml' \ + | grep -Ev '(^|/)(kustomization\.ya?ml|.*\.example\.ya?ml|.*values\.ya?ml|patch-.*\.ya?ml)$' + ) + + if [ "${#manifests[@]}" -eq 0 ]; then + echo "No Kubernetes manifests found." + exit 0 + fi + + docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + ghcr.io/yannh/kubeconform:latest \ + -strict \ + -ignore-missing-schemas \ + -summary \ + "${manifests[@]}" + + build: + if: github.event_name != 'pull_request' && github.ref_name == 'main' + runs-on: [self-hosted, linux, arch, homelab] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Detect changed docker-built services + id: services + shell: bash + run: | + base="${{ github.event.before }}" + if [ -z "$base" ] || [ "$base" = "0000000000000000000000000000000000000000" ]; then + base="$(git rev-list --max-parents=0 HEAD)" + fi + + mapfile -t changed_files < <(git diff --name-only "$base" "${GITHUB_SHA}") + + services=() + + add_service() { + local name="$1" + local seen=0 + for existing in "${services[@]}"; do + if [ "$existing" = "$name" ]; then + seen=1 + break + fi + done + if [ "$seen" -eq 0 ]; then + services+=("$name") + fi + } + + for file in "${changed_files[@]}"; do + case "$file" in + dtek_notif/*) + add_service dtek_notif + ;; + errorpages/*) + add_service errorpages + ;; + userbot/*) + add_service userbot + ;; + homepages/*) + add_service homepages + ;; + edu_master/phpsessid-bot/*|edu_master/webinar-checker/*|edu_master/compose.yaml) + add_service edu_master + ;; + esac + done + + if [ "${#services[@]}" -eq 0 ]; then + echo "No docker-built services changed." + echo "services=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + printf '%s\n' "${services[@]}" | tee /tmp/services.txt + echo "services=$(paste -sd, /tmp/services.txt)" >> "$GITHUB_OUTPUT" + + - name: Log in to registry + if: steps.services.outputs.services != '' + shell: bash + run: | + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "${REGISTRY}" \ + -u "${{ secrets.REGISTRY_USERNAME }}" \ + --password-stdin + + - name: Build and push changed images + if: steps.services.outputs.services != '' + shell: bash + run: | + IFS=, read -r -a services <<< "${{ steps.services.outputs.services }}" + + for service in "${services[@]}"; do + case "$service" in + dtek_notif) + docker build -t "${REGISTRY}/forust/dtek-notif:latest" dtek_notif + docker push "${REGISTRY}/forust/dtek-notif:latest" + ;; + errorpages) + docker compose -f errorpages/compose.yaml build errorpage + docker compose -f errorpages/compose.yaml push errorpage + ;; + userbot) + docker compose -f userbot/compose.yaml build forust + docker compose -f userbot/compose.yaml push forust + ;; + homepages) + docker compose -f homepages/compose.yaml build forust xdfnx + docker compose -f homepages/compose.yaml push forust xdfnx + ;; + edu_master) + docker compose -f edu_master/compose.yaml build session-keeper webinar-checker + docker compose -f edu_master/compose.yaml push session-keeper webinar-checker + ;; + esac + done diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml deleted file mode 100644 index 3b8e336..0000000 --- a/.github/workflows/lint.yaml +++ /dev/null @@ -1,90 +0,0 @@ -name: lint - -on: - push: - branches: - - "**" - pull_request: - workflow_dispatch: - -jobs: - prettier: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Check formatting with Prettier - shell: bash - run: | - mapfile -t prettier_files < <( - git ls-files \ - | grep -E '\.(md|json|ya?ml|html|css)$' \ - | grep -Ev '^(\.docs/|\.zed/|errorpages/html/|homepages/(forust_files|xdfnx_files)/)' - ) - - if [ "${#prettier_files[@]}" -eq 0 ]; then - echo "No Prettier-managed files found." - exit 0 - fi - - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - node:22-alpine \ - sh -lc 'npx --yes prettier@3 --check --ignore-unknown "$@"' sh "${prettier_files[@]}" - - ruff: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint Python with Ruff - shell: bash - run: | - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - ghcr.io/astral-sh/ruff:latest \ - check . - - yamllint: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint YAML syntax - shell: bash - run: | - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - cytopia/yamllint:latest \ - -c .yamllint . - - hadolint: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint Dockerfiles - shell: bash - run: | - mapfile -t dockerfiles < <( - git ls-files ':(glob)**/Dockerfile' ':(glob)**/Dockerfile.*' - ) - - if [ "${#dockerfiles[@]}" -eq 0 ]; then - echo "No Dockerfiles found." - exit 0 - fi - - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - --entrypoint hadolint \ - hadolint/hadolint:latest-debian \ - -c .hadolint.yaml "${dockerfiles[@]}" diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml deleted file mode 100644 index f29dddd..0000000 --- a/.github/workflows/validate.yaml +++ /dev/null @@ -1,52 +0,0 @@ -name: validate - -on: - push: - branches: - - "**" - pull_request: - workflow_dispatch: - -jobs: - yaml: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Lint YAML syntax - shell: bash - run: | - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - cytopia/yamllint:latest \ - -c .yamllint . - - k8s: - runs-on: [self-hosted, linux, arch, homelab] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Validate Kubernetes manifests - shell: bash - run: | - mapfile -t manifests < <( - git ls-files ':(glob)**/k8s/**/*.yaml' ':(glob)**/k8s/**/*.yml' \ - | grep -Ev '(^|/)(kustomization\.ya?ml|.*\.example\.ya?ml|.*values\.ya?ml|patch-.*\.ya?ml)$' - ) - - if [ "${#manifests[@]}" -eq 0 ]; then - echo "No Kubernetes manifests found." - exit 0 - fi - - docker run --rm \ - -v "$PWD:/work" \ - -w /work \ - ghcr.io/yannh/kubeconform:latest \ - -strict \ - -ignore-missing-schemas \ - -summary \ - "${manifests[@]}"