-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: squash Alembic migrations; eliminate non-self-contained data-migration tests #1517
Conversation
d05b558
to
d390264
Compare
Not captured by securedrop-client/alembic/versions/86b01b6290da_add_reply_draft.py Lines 28 to 38 in 8c372ca
To do:
I've confirmed with @creviera that this pull request (with these changes) does not need to be ready for tomorrow's release-readiness check, so this will fall through to testing in a subsequent |
e3c81a4
to
557ab3a
Compare
Note that, as this is a breaking change requiring a clean installation (or at least deleting |
Reviewing... : ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test Plan
Against a staging or production SecureDrop server, follow these steps in sd-app
rather than sd-dev
.
⚠️ I've tested this on asd-dev
instance, against the recommendation, because I didn't have ansd-app
at hand.
- In-place upgrade fails: 🍏
git checkout main
ls -al ~/.securedrop_client/svs.sqlite
rm svs.sqlite
alembic upgrade head
git checkout 1500-squash-alembic
alembic upgrade head
# INFO [alembic.runtime.migration] Context impl SQLiteImpl.
# INFO [alembic.runtime.migration] Will assume non-transactional DDL.
# ERROR [alembic.util.messaging] Can't locate revision identified by '9ba8d7524871'
# FAILED: Can't locate revision identified by '9ba8d7524871'
- A fresh installation succeeds: 🍏
git checkout 1500-squash-alembic
ls -al ~/.securedrop_client/svs.sqlite
rm svs.sqlite
alembic upgrade head
# INFO [alembic.runtime.migration] Context impl SQLiteImpl.
# INFO [alembic.runtime.migration] Will assume non-transactional DDL.
# INFO [alembic.runtime.migration] Running upgrade -> d7c8af95bc8e, empty message
⚠️ There are changes here in how I tested that the app ran normally, agian because ofsd-dev
instead ofsd-app
:
# Finally:
cd ~/src/securedrop-client
git checkout 1500-squash-alembic
rm svs.sqlite
alembic upgrade head
cp svs.sqlite ~/.securedrop-client/svs.sqlite
sha256sum ~/.securedrop-client/svs.sqlite # for future reference
# ebabf002228da8a1e936158bb6ffc3a494c4ef6d693dd1a394f263fb1941a3bb /home/user/.securedrop-client/svs.sqlite
LOGLEVEL=debug ./run.sh --sdc-home ~/.securedrop-client/
# Downloaded files, deleted some, deleted source account...
sha256sum ~/.securedrop-client/svs.sqlite # Changes are expected, to make sure the database in use was the one previously re-created by alembic.
# c71f3b916bd72c2a840659ab64bee498a794b82d5cd48bbbf111b83dad8608fd /home/user/.securedrop-client/svs.sqlite
# OK
- The Client runs normally.
Additional tests
I've directly compared the resulting databases for both migration paths, as follows:
# Get a text representation of the original database
cd ~/src/securedrop-client
git checkout main
rm svs.sqlite
alembic upgrade head
sha256sum svs.sqlite
# 39a47c16e9ad9376e9d0339df3bc61462fd2a83bcc42d3e89e2701ebe573dc3f svs.sqlite
sqlite3 svs.sqlite .dump > old.sql
# Get a text representation of the new database
git checkout 1500-squash-alembic
rm svs.sqlite
alembic upgrade head
sha256sum svs.sqlite
# 57dd72783fa1cc6194905b05e2c5858a24e45d9c1d589fc87206466f8c324729 svs.sqlite
sqlite3 svs.sqlite .dump > new.sql
# Compare them:
diff -u old.sql new.sql
# See result in the gist below.
👉 Result of the comparison between old.sql and
new.sql`. I pasted it in a gist because it's too long to be comfortable to read inline. (gist)
There are some order and indentation changes that are not meaningful. After eliminating those, the only significant differences are:
--- old.sql 2022-06-30 12:50:00.742905752 +1000
+++ new.sql 2022-06-30 12:49:34.854907411 +1000
+ INSERT INTO replysendstatuses VALUES(1,'PENDING');
+ INSERT INTO replysendstatuses VALUES(2,'FAILED');
+ INSERT INTO downloaderrors VALUES(1,'CHECKSUM_ERROR');
+ INSERT INTO downloaderrors VALUES(2,'DECRYPTION_ERROR');
- Both migration paths result in equivalent databases 🍊
I'm kinda stopping for a moment before ticking that last box. However:
- @cfm My understanding is that you've got these changes well in mind, I just don't quite understand them. (It might be I need to read the context again with a fresh mind!)
- In any case, they're additions, that I don't see could cause trouble, even if it turned out were not present in the database after following the original migration path.
So things are looking pretty good to me. On the testing side (as in files in tests/
), I'll take a fresh look next week, but the rationale makes complete sense and the corresponding docs / PR template additions are 👍. 🍏 🍏
Thanks for reviewing, @gonzalo-bulnes! Diffing the |
The context: These The omission: The
This is done, with the expected diff itself minimized by 3211967. Let me know what you think, @gonzalo-bulnes! |
a14db6c
to
3211967
Compare
❤️ The addition to the test plan looks great @cfm! (I didn't think of reformatting the SQL files automatically and removed the common lines by hand 🙈) I'll review again and see if the enums situation is still unclear to me 🙂 P.S.: I think I'm with you on the enum values in the database. Maybe that was a initially cautious move for an enum which values turned out not to change that often? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enum values
Nice, I'm happy to report that the statements that insert enum values are still there, but clearly were there in the old database too. So I have no more questions on that side. 👍
- The diff between the current and the new migration path is clean. 🍏
Tests
We are not testing the outcome of that initial migration. Are we okay with that? (I am okay with that, since migrations are immutable, I don't see a lot of value in having automated test suites for them anyway.)
Nitpicking
Currently, the only migration is called d7c8af95bc8e_.py
, maybe we could call it something like d7c8af95bc8e_intial_dababase_structure.py
so that we don't have to modify it when adding new migration with nice names? (And to avoid that trailing underscore? 😬)
Making this an approving review (feel free to ignore the naming suggestion @cfm). If we're happy with the automated testing level, I think were ready to ship this 🙂
Thanks, @gonzalo-bulnes!
What testing would you look for here beyond that done by securedrop-client/tests/test_alembic.py Lines 100 to 104 in 69c3d7a
I tend to favor minimal Alembic version names (as opposed to descriptions). But in the revised c75bf83 I've done a quick |
BREAKING CHANGE: The "securedrop-client" entry-point will expect a nonexistent or empty database and migrate it to new revision d7c8af95bc8e. It will error out if a database already exists at another, prior revision.
Data-migration tests MUST not use models from securedrop_client.db, which will always contain the definitions from Git's head, not those corresponding to the Alembic head under test.
Data-migration tests MUST be self-contained in order to test the schema as of the Alembic version under test, not the current Git head.
The test scaffolding in tests.test_alembic shouldn't be coupled to the implementation under test in securedrop_client.db.
The SQL statements generated by "sqlite3 svs.sqlite .dump" replicate the database's tables and columns in the order in which they were originally added. For the current database schema, that's a hybrid of the order in which they're defined in securedrop_client.db and subsequent additions in migrations; in the new database schema, that's strictly their ordering in securedrop_client.db. The latter artificially inflates the diff of comparing "sqlite3 svs.sqlite .dump" for the old and new schemas. For ease of review, here we attempt to replicate the current SQL statements as closely as possible, for as small a diff as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolutely right on the tests @cfm! I somehow got fixated on the individual migration test files. (Which are the one that were mostly problematic. 💡) Testing that the migrations were all applied is the test I think always makes sense to have! 🍏 Thanks for the pointers : )
Thanks for indulging me on the d7c8af95bc8e_initial.py
. Truth is that the following might not happen often or at all, but I've found that having a rough idea of which migration does what can be a great help with troubleshooting. Especially if the automated naming pattern accommodates for having a descriptive slug, I'd rather have one however short it is ❤️
Thank you for your thorough work @cfm! I'll shipping this 🚀
Description
BREAKING CHANGE. Fixes #1500 by:
9ba8d7524871
;Test Plan
Against a staging or production SecureDrop server, follow these steps in
sd-app
rather thansd-dev
.A SQL diff shows only insignificant differences in whitespace/ordering and the inlining of
CONSTRAINT
s:main
and1500-squash-alembic
, runalembic upgrade head
and save the databases to (e.g.){old,new}.sqlite
.sqlfluff fix
and ultimately resorted to https://codebeautify.org/sqlformatter.The Client runs normally.
Checklist
If these changes modify code paths involving cryptography, the opening of files in VMs or network (via the RPC service) traffic, Qubes testing in the staging environment is required. For fine tuning of the graphical user interface, testing in any environment in Qubes is required. Please check as applicable:
If these changes add or remove files other than client code, the AppArmor profile may need to be updated. Please check as applicable:
If these changes modify the database schema, you should include a database migration. Please check as applicable:
main
and confirmed that the migration applies cleanlymain
and would like the reviewer to do so