Skip to content

Conversation

@ViktorT-11
Copy link
Contributor

Previously, SQL migrations and code migrations have been designed to be a single migration version, where the SQL migration was run first, followed by a post step migration callback that executed the code migration.

Due to a re-definition of the migration design, which separates SQL and code migrations, we need to update tapd to become compatible with the new migration design before updating to the new design.

This PR therefore separates the code migrations from migration 33 & 37, into separate migration files, and adds those two new migrations to the tapdb/sqlc/migrations directory.

Additionally, since users that have already run the code migrations during migration 33 & 37 will have those migrations re-executed once more after updating to this PR, we test that re-execution of those code migrations will be a no-op for those users, and won't add or change any data in the database.

@ViktorT-11 ViktorT-11 changed the title tapd+sqlc: separate SQL migrations from code migs tapd+sqlc: separate SQL migrations from code migrations Nov 21, 2025
@gemini-code-assist
Copy link

Summary of Changes

Hello @ViktorT-11, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request implements a significant refactoring of the migration system within tapd to align with a new design philosophy that mandates a clear separation between SQL schema changes and application-level code migrations. By extracting existing code migrations from their original combined SQL/code versions (33 and 37) into new, standalone migration files (48 and 49), the system gains greater modularity and clarity. A key focus of this change is ensuring that this transition is seamless for existing users, with robust testing confirming that the re-execution of these now-separated code migrations will not introduce any unintended side effects or data modifications.

Highlights

  • Migration Separation: SQL and code migrations are now distinctly separated, moving away from a combined version design.
  • Code Migration Re-versioning: Code migrations originally part of versions 33 and 37 have been extracted into new, dedicated migration files (versions 48 and 49).
  • Idempotency Testing: New tests ensure that re-executing these separated code migrations (48 and 49) is a no-op for users who have already run the original combined migrations, preventing data duplication or corruption.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@ViktorT-11
Copy link
Contributor Author

Will address any failing CI checks on Monday.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively separates SQL migrations from code migrations for versions 33 and 37 by moving the code migration logic to new, dedicated migration versions 48 and 49. This is a solid architectural improvement that enhances the clarity and maintainability of the migration process.

The new tests, TestMigration48ScriptKeyTypeReplay and TestMigration49BurnReplay, are well-designed and crucial for ensuring backward compatibility. They correctly simulate the upgrade path for existing users and verify that re-running the code migrations is idempotent, which is essential for a safe transition.

However, there is one critical issue: the LatestMigrationVersion constant in tapdb/migrations.go has not been updated to 49. The comment for this constant explicitly states that it must be updated when new migrations are added. Failing to do so can compromise the database downgrade protection mechanism. Please ensure this constant is updated to reflect the new latest migration version.

@coveralls
Copy link

coveralls commented Nov 21, 2025

Pull Request Test Coverage Report for Build 19631813200

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 8261 unchanged lines in 123 files lost coverage.
  • Overall coverage decreased (-0.03%) to 56.554%

Files with Coverage Reduction New Missed Lines %
authmailbox/client.go 2 66.67%
commitment/proof.go 2 87.29%
fn/iter.go 2 62.07%
fn/retry.go 2 92.5%
universe_rpc_diff.go 2 76.0%
universe/syncer.go 2 84.22%
universe/interface.go 3 73.97%
commitment/encoding.go 4 68.75%
mssmt/encoding.go 4 76.67%
rpcserver.go 4 61.49%
Totals Coverage Status
Change from base Build 19570339755: -0.03%
Covered Lines: 64332
Relevant Lines: 113753

💛 - Coveralls

Previously, SQL migrations and code migrations have been designed to be
a single migration version, where the SQL migration was run first,
followed by a post step migration callback that executed the code
migration.

Due to a re-definition of the migration design, which separates SQL and
code migrations, we need to update tapd to become compatible with the
new migration design before updating to the new design.

This commit therefore separates the code migrations from migration `33`
& `37`, into separate migration files, and adds those two new migrations
to the `tapdb/sqlc/migrations` directory.

Additionally, since users that have already run the code migrations
during migration `33` & `37` will have those migrations re-executed once
more after updating to this PR, we test that re-execution of those
code migrations will be a no-op for those users, and won't add or change
any data in the database.
With the separation of code migrations and SQL migrations in added with
the previous commit, it now makes sense to not re-execute a code
migration during a database downgrade. Therefore, we need to loosen the
strictness of the check-migration-numbering.sh script, to allow for
missing .down.sql files for code migrations specifically.

This commit implements this change.
@jtobin
Copy link
Member

jtobin commented Nov 24, 2025

The failing tapgarden unit test passes for me locally on this branch. I'll kick the CI job again and see if it proves flaky here.

(EDIT: yeah, it was a flake.)

@ffranr ffranr requested review from ffranr and jtobin November 24, 2025 15:10
@ffranr ffranr moved this from 🆕 New to 🏗 In progress in Taproot-Assets Project Board Nov 24, 2025
@ffranr ffranr moved this from 🏗 In progress to 👀 In review in Taproot-Assets Project Board Nov 24, 2025
Copy link
Contributor

@ffranr ffranr left a comment

Choose a reason for hiding this comment

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

Nice! I thought this would be a bigger change for some reason, nice surprise.

I think we should hold off on merging this until lightninglabs/migrate#3 is final.

Comment on lines +771 to +777
// Executing the code migration again (now at migration 48) should not
// change or add any new values than the values assigned when the code
// migration was run for migration version 33.
err = db.ExecuteMigrations(TargetLatest, WithPostStepCallbacks(
makePostStepCallbacks(db, postMigrationChecks),
))
require.NoError(t, err)
Copy link
Contributor

@ffranr ffranr Nov 25, 2025

Choose a reason for hiding this comment

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

Target 48 explicitly here? TargetVersion(48) Or maybe that's not necessary and I'm missing something.

Copy link
Contributor

Choose a reason for hiding this comment

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

Same below for TargetVersion(49).

Copy link
Contributor

Choose a reason for hiding this comment

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

might be nice to have const values for migration numbers (33, 49 and 48, etc) in these unit tests. Start/replacement. Maybe?

Comment on lines +56 to +60
# Error if the .up.sql is an SQL migration, but we're missing the
# corresponding .down.sql. This doesn't apply if the .up.sql file is a code
# migration.
if is_sql_migration "$base_filename.up.sql" && \
[ ! -f "$base_filename.down.sql" ]; then
Copy link
Contributor

Choose a reason for hiding this comment

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

Updated:

Do we need to include this commit? Is it required for your end goal?

We don’t often have no-op down migrations, but IMO it’s fine to include them. It keeps the migration sequence contiguous, and IMO it’s cleaner to always provide a down file for every up, even if the down is empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we need to include this commit? Is it required for your end goal?

It’s not required, but I want to explain why I think this change is beneficial.

This change specifically targets code migrations, allowing them to omit a down.sql file when appropriate.

To illustrate why SQL and code migrations should behave differently, consider the following example of migrations:

  • 0001_example.up.sql
    CREATE TABLE example (id INTEGER PRIMARY KEY);

  • 0001_example.down.sql
    DROP TABLE example;

  • Followed by a code migration:
    0002_example_code_migration.up.sql
    (This migration inserts data into the example table.)

If we also add a down.sql for the code migration:

  • 0002_example_code_migration.down.sql
    (This would simply re-run the code migration and insert the data again.)

This highlights the mismatch:

  • For SQL migrations, the down.sql undoes the up.sql.
  • For code migrations, a down.sql would unintentionally re-execute the migration instead of undoing the changes.
    In this example, the data inserted by the code migration would actually be removed only when the table itself is dropped by 0001_example.down.sql.

Currently, the code migrations in tapd are structured as no-ops when re-executed, but that assumption can't be true for all code migrations. For example, it'd be much more complex for migrations like the kvdb → SQL migration in litd.


For that reason, I think the code migration itself should indicate whether a down.sql should be present or not, rather than having CI enforce for all types of migrations. The migrate library explicitly supports migrations without a down.sql file, and I think this is a case where that functionality makes sense to use.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don’t often have no-op down migrations, but IMO it’s fine to include them. It keeps the migration sequence contiguous, and IMO it’s cleaner to always provide a down file for every up, even if the down is empty.

And just to clarify, this if clause here will only trigger when the up.sql case contains any executable content, i.e. when the up.sql is an SQL migration. It's not checking if the down.sql file is empty.

Copy link
Member

@jtobin jtobin left a comment

Choose a reason for hiding this comment

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

LGTM. 👍 👍 The only change I would suggest is to more explicitly reference the migration design change in your commit message (e.g. by issue/PR, etc.) so that the source is better-captured in the history.

@ViktorT-11
Copy link
Contributor Author

Thanks for the reviews @ffranr & @jtobin 🎉! It'll address your feedback and rebase on main once lightninglabs/migrate#3 is final 🚀

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

Projects

Status: 👀 In review

Development

Successfully merging this pull request may close these issues.

4 participants