Skip to content

Install smoke test for all three databases; make a fresh install work on MySQL - #652

Merged
compscidr merged 2 commits into
mainfrom
ci/install-smoke-test
Oct 3, 2026
Merged

compscidr merged 2 commits into
mainfrom
ci/install-smoke-test

Conversation

@compscidr

Copy link
Copy Markdown
Collaborator

Closes #651.

Install smoke test

scripts/install-smoke-test.sh sqlite|mysql|postgres builds 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:

  1. / shows the database wizard.
  2. Test Database: an empty type and (MySQL/Postgres) a wrong password are refused with 400; the right details return 200.
  3. /wizard_db saves the database step; / then connects, migrates and shows the settings step.
  4. PATCH /api/v1/settings saves the site title; /?page=auth shows the auth step.
  5. Placeholder client_id/client_secret are appended to .env and the container is restarted.
  6. The home page shows the saved title and no wizard; /login, /search, /robots.txt, /rss.xml, /sitemap.xml and the theme stylesheet return 200, an unknown path 404, and /admin redirects when logged out.
  7. The server log has no panic and no SQL error.

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:

  • Migration failed with Error 1170: BLOB/TEXT column 'slug' used in key specification without a key length. pages.slug, post_types.slug and external_backlinks.referer are 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.
  • Every settings query failed with a syntax error, because key is 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 on settings, plugin_settings and 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 rows alias (ROWS is reserved in MySQL 8) and LIKE … ESCAPE '\', which MySQL reads as an unterminated string. The escape character is now !.

Testing

  • go test ./... passes (SQLite; the Postgres tests run in CI).
  • The smoke test passes locally for sqlite, mysql (9.6) and postgres (16).
  • The plugin store changes are not exercised on MySQL: there are no MySQL unit tests and the smoke test installs no plugin that uses the store.

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

compscidr and others added 2 commits October 3, 2026 08:04
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

codecov Bot commented Oct 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.92308% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
plugin/store.go 72.72% 1 Missing and 2 partials ⚠️
admin/admin.go 0.00% 1 Missing ⚠️
plugins/directory/directory.go 0.00% 0 Missing and 1 partial ⚠️
tools/migrate.go 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@compscidr
compscidr merged commit ff0e752 into main Oct 3, 2026
6 of 7 checks passed
@compscidr
compscidr deleted the ci/install-smoke-test branch October 3, 2026 15:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Test workflow 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.Column forms, and fixed the plugin store's rows alias and LIKE ... ESCAPE escape 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

need some type of install smoke test

2 participants