diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2f397f3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: CI + +# До появления этого workflow тесты гонялись только по push в dev, то есть уже +# после мержа: сломанный pull request был зелёным до последнего момента, а падение +# обнаруживалось на dev, когда образ уже собирался. +on: + pull_request: + +# Новый пуш в ветку PR отменяет предыдущий прогон — иначе очередь копит проверки +# коммитов, которые уже неактуальны. +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + gate: + uses: ./.github/workflows/gate.yml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 63c091e..23ec1f3 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -16,24 +16,10 @@ env: IMAGE_NAME: ghcr.io/lecturelog/lecturelog-web jobs: + # Тот же гейт, что и на pull request — единое определение в gate.yml, + # чтобы проверки PR не могли разойтись с тем, что гейтит публикацию образа. gate: - name: Gate - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - cache: true - - - name: Run gate - run: make gate - - - name: Check generated artifacts - run: git diff --exit-code + uses: ./.github/workflows/gate.yml publish: name: Publish image diff --git a/.github/workflows/gate.yml b/.github/workflows/gate.yml new file mode 100644 index 0000000..eeca2cc --- /dev/null +++ b/.github/workflows/gate.yml @@ -0,0 +1,48 @@ +name: Gate + +# Переиспользуемый workflow: один и тот же прогон вызывается и на pull request, +# и перед публикацией образа. Вынесен отдельно намеренно — если бы проверки PR +# и предпубликационный гейт были описаны двумя копиями, они бы со временем +# разошлись, и получилось бы худшее из возможного: PR зелёный, а dev красный. +on: + workflow_call: + +permissions: + contents: read + +jobs: + gate: + name: Сборка, vet, тесты + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Setup Go + uses: actions/setup-go@v7 + with: + go-version-file: go.mod + cache: true + + # Версия Tailwind CLI живёт в Makefile — берём её оттуда, чтобы ключ кэша + # инвалидировался ровно при обновлении версии, а не при любой правке Makefile. + - name: Определить версию Tailwind CLI + id: tw + run: echo "version=$(grep -m1 '^TAILWIND_VERSION' Makefile | awk '{print $3}')" >> "$GITHUB_OUTPUT" + + # Цель tailwind-bin пропускает скачивание, если бинарь уже на месте, + # поэтому кэш экономит ~120 МБ загрузки на каждом прогоне. + - name: Кэш Tailwind CLI + uses: actions/cache@v6 + with: + path: bin/tailwindcss + key: tailwind-${{ runner.os }}-${{ steps.tw.outputs.version }} + + - name: Прогон гейта + run: make gate + + # make gate перегенерирует templ и Tailwind. Если закоммиченные *_templ.go + # или static/css/app.css расходятся с результатом генерации — падаем здесь: + # в рантайме отдаётся именно закоммиченный артефакт, а не собранный на месте. + - name: Проверка детерминизма артефактов + run: git diff --exit-code