Repository navigation
Install smoke test for all three databases; make a fresh install work on MySQL - #652
Conversation
Two things stopped goblog running on MySQL at all: - AutoMigrate failed with error 1170. pages.slug, post_types.slug and external_backlinks.referer are text columns with a unique index, and MySQL cannot index a text column without a key length. The index tags now carry one; the SQLite and Postgres drivers ignore it. - Every query on the settings, plugin_settings and plugin store tables named the key column in a raw condition, and KEY is a reserved word in MySQL. Those conditions are now maps (or clause.Column), which GORM quotes for the database in use. The plugin store also aliased a count as rows, reserved in MySQL 8, and escaped LIKE patterns with a backslash, which MySQL reads as escaping the closing quote of ESCAPE '\'; the escape character is now '!'. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
scripts/install-smoke-test.sh starts a fresh goblog container, walks the install wizard the way a browser would (test the database, save it, save the settings), and checks the site comes up and survives a restart with nothing but 'record not found' in the log. A new workflow runs it for each database on every push. The wizard's GitHub OAuth step cannot run in CI, so the script writes placeholder credentials to .env instead; the first admin login is not covered. Closes #651. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It changes database schema (unique-index definitions) and rewrites many persistence-layer query conditions across three databases, including a plugin-store path the author notes is untested on MySQL, which warrants human verification.
Review effort: Balanced
Findings: None
What changed in this PR
This PR adds an end-to-end install smoke test that exercises GoBlog's install wizard against SQLite, MySQL, and Postgres (closing #651), and fixes the MySQL incompatibilities that the test uncovered. It fits into the codebase as a CI safety net for the fresh-install path plus targeted database-portability fixes in the persistence layer.
The MySQL fixes fall into two buckets: (1) schema — text columns (pages.slug, post_types.slug, external_backlinks.referer) with unique indexes now carry a MySQL key length, which SQLite/Postgres ignore; (2) queries — conditions referencing the reserved word key (and the rows alias / backslash LIKE ESCAPE) are rewritten into GORM map/clause.Column forms that each dialect quotes correctly.
Changes:
- New
scripts/install-smoke-test.sh+Install Smoke Testworkflow running a 3-database matrix on push. - Added MySQL index key lengths to text-column unique indexes (
length:191/length:255), ignored by other DBs. - Rewrote ~15 raw
key-based SQL conditions to GORM map/clause.Columnforms, and fixed the plugin store'srowsalias andLIKE ... ESCAPEescape character.
| File | Description |
|---|---|
| scripts/install-smoke-test.sh | New smoke test that walks the install wizard with curl against one database. |
| .github/workflows/install-smoke.yml | New workflow running the smoke test as a sqlite/mysql/postgres matrix. |
| README.md | Documents how to run the smoke test locally. |
| tools/migrate.go | Converts settings/plugin migration conditions to map/clause.Column forms; adds clause import. |
| blog/blog.go | Settings lookups use map conditions to quote key per dialect. |
| auth/otp.go | siteTitle settings lookup uses a map condition. |
| admin/admin.go | GetSetting lookup uses a map condition. |
| plugins/directory/directory.go | siteURL settings lookup uses a map condition. |
| plugin/registry.go | Plugin-setting FirstOrCreate/Assign conditions use map conditions. |
| plugin/store.go | Renames rows alias to row_count, switches to .Not()/clause.Column, and changes LIKE escape char to !. |
| blog/page.go, blog/post_type.go | Slug unique index gains length:191 for MySQL. |
| blog/post.go | Referer unique index gains length:255 for MySQL. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Closes #651.
Install smoke test
scripts/install-smoke-test.sh sqlite|mysql|postgresbuilds the Docker image, starts a fresh container (plus a MySQL or Postgres container on the same network), and walks the install wizard with curl the way a browser does:/shows the database wizard./wizard_dbsaves the database step;/then connects, migrates and shows the settings step.PATCH /api/v1/settingssaves the site title;/?page=authshows the auth step.client_id/client_secretare appended to.envand the container is restarted./login,/search,/robots.txt,/rss.xml,/sitemap.xmland the theme stylesheet return 200, an unknown path 404, and/adminredirects when logged out.A new workflow, Install Smoke Test, runs it on every push as a three-way matrix.
Not covered: the wizard's last step sends the user to GitHub to authorise an OAuth app, which CI cannot do. GitHub's callback, and the first admin login, are untested. Because the callback is also what registers the site's routes, the script restarts the container to get them; that doubles as the "survives a restart" check.
MySQL was broken
The first run of the test failed on MySQL, in two layers:
Error 1170: BLOB/TEXT column 'slug' used in key specification without a key length.pages.slug,post_types.slugandexternal_backlinks.refererare text columns with a unique index. The index tags now carry a key length, which the SQLite and Postgres drivers ignore, so nothing changes on those databases.keyis a reserved word in MySQL and the conditions named it raw (Where("key = ?", …)). The page still rendered, with every setting read as its default. Fifteen conditions onsettings,plugin_settingsand the plugin store are now maps, which GORM quotes per database.Also fixed in the plugin store, found by reading rather than by the test: a
COUNT(*) AS rowsalias (ROWSis reserved in MySQL 8) andLIKE … ESCAPE '\', which MySQL reads as an unterminated string. The escape character is now!.Testing
go test ./...passes (SQLite; the Postgres tests run in CI).Note for existing MySQL sites
I doubt there are any, given the above. If there is one, its tables predate these failures and AutoMigrate will try to add the missing unique indexes.
🤖 Generated with Claude Code