mirror of
https://github.com/go-admin-team/go-admin.git
synced 2026-09-25 19:36:07 +00:00
MySQL is the dialect most installations run and the only registered driver with no service here. The scheduler lease that follows reads the database's clock, and the first implementation read it as a timestamp: over go-admin's own `parseTime=True&loc=Local` DSN, MySQL's UTC_TIMESTAMP comes back relabelled as local time, so on any host that is not UTC every lease was one zone offset out. Every assertion that compared the lease only against itself still passed, and the three dialects already here could not see it. The DSN keeps loc=Local on purpose: it is what config/settings.yml ships. A DSN here that quietly differed would test a configuration nobody runs.
195 lines
7.5 KiB
YAML
195 lines
7.5 KiB
YAML
name: build
|
|
|
|
on:
|
|
push:
|
|
branches: [ master, dev ]
|
|
tags: [ 'v*', '[0-9]*' ]
|
|
pull_request:
|
|
branches: [ master ]
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
IMAGE_NAME: ${{ github.repository }}
|
|
|
|
jobs:
|
|
|
|
build:
|
|
name: Build
|
|
runs-on: ubuntu-latest
|
|
|
|
# The queue's ordering rule - consumers registered before the queue is
|
|
# started - is invisible on the memory backend, which is the default and
|
|
# therefore what every other test runs on: queue.Memory's Register starts a
|
|
# consumer goroutine whatever the state. Only redis refuses a late
|
|
# registration, so without a server here the tests that cover it would skip
|
|
# and the suite would report success for a queue that accepts no consumers.
|
|
services:
|
|
redis:
|
|
image: redis:7-alpine
|
|
ports:
|
|
- 6379:6379
|
|
options: >-
|
|
--health-cmd "redis-cli ping"
|
|
--health-interval 5s
|
|
--health-timeout 3s
|
|
--health-retries 10
|
|
|
|
postgres:
|
|
image: postgres:15-alpine
|
|
env:
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: goadmin_test
|
|
ports:
|
|
- 5432:5432
|
|
options: >-
|
|
--health-cmd "pg_isready -U postgres"
|
|
--health-interval 5s
|
|
--health-timeout 3s
|
|
--health-retries 10
|
|
|
|
# The fourth registered driver, and the one that disagrees with the
|
|
# other three about NULL: its unique index treats two NULLs as equal and
|
|
# permits one. A migration that builds a unique index over a nullable
|
|
# column therefore fails here and nowhere else, which is how one shipped
|
|
# that no SQL Server database could apply at all - not even an empty
|
|
# one. The password is this container's only credential and the
|
|
# container lives for the length of one job.
|
|
sqlserver:
|
|
image: mcr.microsoft.com/mssql/server:2022-latest
|
|
env:
|
|
ACCEPT_EULA: "Y"
|
|
MSSQL_SA_PASSWORD: GoAdmin_Test1
|
|
MSSQL_PID: Developer
|
|
ports:
|
|
- 1433:1433
|
|
options: >-
|
|
--health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P GoAdmin_Test1 -C -Q 'SELECT 1'"
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 20
|
|
--health-start-period 20s
|
|
|
|
# The dialect most installations actually run, and until the
|
|
# scheduler lease (#915) the only one with no service here. The lease
|
|
# reads the database's clock, and the first implementation read it as
|
|
# a timestamp: over go-admin's own `parseTime=True&loc=Local` DSN,
|
|
# MySQL's UTC_TIMESTAMP comes back relabelled as local time, so on any
|
|
# host that is not UTC every lease was one zone offset out - and every
|
|
# assertion that compared the lease only against itself still passed.
|
|
# The three dialects that were here could not see it.
|
|
mysql:
|
|
image: mysql:8
|
|
env:
|
|
MYSQL_ROOT_PASSWORD: GoAdmin_Test1
|
|
MYSQL_DATABASE: goadmin_test
|
|
ports:
|
|
- 3306:3306
|
|
options: >-
|
|
--health-cmd "mysqladmin ping -h 127.0.0.1 -uroot -pGoAdmin_Test1"
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 20
|
|
--health-start-period 20s
|
|
|
|
env:
|
|
GO_ADMIN_TEST_REDIS_ADDR: 127.0.0.1:6379
|
|
# The soft-delete conversion drops an index, and gorm's PostgreSQL driver
|
|
# produced unparseable SQL for that - on SQLite, where the rest of these
|
|
# tests run, the same code works. The suite reported success for a
|
|
# migration that failed on every PostgreSQL database it was pointed at.
|
|
# See go-admin#919.
|
|
GO_ADMIN_TEST_POSTGRES_DSN: "host=127.0.0.1 port=5432 user=postgres password=postgres dbname=goadmin_test sslmode=disable"
|
|
GO_ADMIN_TEST_SQLSERVER_DSN: "sqlserver://sa:GoAdmin_Test1@127.0.0.1:1433?database=goadmin_test"
|
|
# loc=Local on purpose: it is what config/settings.yml ships and what
|
|
# made the timezone defect above reachable. A DSN here that quietly
|
|
# differed from the one installations use would test a configuration
|
|
# nobody runs.
|
|
GO_ADMIN_TEST_MYSQL_DSN: "root:GoAdmin_Test1@tcp(127.0.0.1:3306)/goadmin_test?charset=utf8mb4&parseTime=True&loc=Local"
|
|
|
|
steps:
|
|
|
|
- name: Set up Go 1.26
|
|
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
|
with:
|
|
go-version: 1.26.5
|
|
id: go
|
|
|
|
- name: Check out code into the Go module directory
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
# SQL Server has no equivalent of POSTGRES_DB, so the database the DSN
|
|
# names has to be created before the tests run.
|
|
- name: Create the SQL Server test database
|
|
run: |
|
|
docker exec ${{ job.services.sqlserver.id }} /opt/mssql-tools18/bin/sqlcmd \
|
|
-S localhost -U sa -P GoAdmin_Test1 -C \
|
|
-Q "IF DB_ID('goadmin_test') IS NULL CREATE DATABASE goadmin_test"
|
|
|
|
- name: Get dependencies
|
|
run: go mod tidy
|
|
|
|
# Before the tests rather than beside checksilent at the end: a formatting
|
|
# miss is a one-command fix, and finding out about it after five minutes of
|
|
# tests and an end-to-end install is five minutes nobody gets back.
|
|
- name: Formatting
|
|
run: make fmt-check
|
|
|
|
# go build does not compile _test.go, so building alone never ran a single
|
|
# test. This is the only workflow that fires on every push and pull request,
|
|
# which makes it the one place a test gate belongs.
|
|
- name: Test
|
|
run: make test
|
|
|
|
- name: Build
|
|
run: make build
|
|
|
|
# A separate module, so none of the steps above see it: the main module's
|
|
# go.mod, its build and its tests are all unaware of the example
|
|
# application. This is the only thing that exercises an application being
|
|
# installed at all - everything below it runs against an injected engine
|
|
# and a hand-built schema, and none of that can catch an application's
|
|
# init() reaching one registry and not the other.
|
|
- name: End-to-end install and uninstall
|
|
run: make test-e2e
|
|
|
|
# Fails the build on the silent-failure classes listed in
|
|
# tools/checksilent, one of which is the contract boundary: nothing under
|
|
# common/ may import app/. A boundary that is only written down erodes; this
|
|
# is what keeps it true.
|
|
- name: Silent-failure checks
|
|
run: make checksilent
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
|
|
- name: Log in to the Container registry
|
|
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract metadata (tags, labels) for Docker
|
|
id: meta
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
flavor: |
|
|
latest=auto
|
|
tags: |
|
|
type=schedule
|
|
type=ref,event=tag
|
|
type=sha,prefix=,format=long,enable=true,priority=100
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
with:
|
|
context: .
|
|
file: scripts/Dockerfile
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|