Skip to content

Eng 567 record integration version on exec logs#7650

Open
Vagoasdf wants to merge 28 commits intomainfrom
ENG-567_record-integration-version-on-exec-logs
Open

Eng 567 record integration version on exec logs#7650
Vagoasdf wants to merge 28 commits intomainfrom
ENG-567_record-integration-version-on-exec-logs

Conversation

@Vagoasdf
Copy link
Contributor

@Vagoasdf Vagoasdf commented Mar 13, 2026

Ticket 567

Description Of Changes

Adding the integration version to the execution logs.
This would help during testing and monitoring to verify what version of the integration an instance is running

Code Changes

  • Migration that runs a saas version execution log update
  • Adding the saas version for the Retry and start Graph task´s log.
  • Adding the version as a column to the execution log on the view of the events

Steps to Confirm

  1. Set up two saas integrations (any)
  2. execute an access request
  3. verify that both saas integrations are showing their version in the execution log

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • Ensure that your downrev is up to date with the latest revision on main
    • Ensure that your downgrade() migration is correct and works
      • If a downgrade migration is not possible for this change, please call this out in the PR description!
    • No migrations
  • Documentation:
    • Documentation complete, PR opened in fidesdocs
    • Documentation issue created in fidesdocs
    • If there are any new client scopes created as part of the pull request, remember to update public-facing documentation that references our scope registry
    • No documentation updates required

@vercel
Copy link
Contributor

vercel bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
fides-plus-nightly Ignored Ignored Preview Mar 19, 2026 2:56pm
fides-privacy-center Ignored Ignored Mar 19, 2026 2:56pm

Request Review

@Vagoasdf Vagoasdf marked this pull request as ready for review March 17, 2026 14:42
@Vagoasdf Vagoasdf requested review from a team as code owners March 17, 2026 14:42
@Vagoasdf Vagoasdf requested review from johnewart and removed request for a team March 17, 2026 14:42
@Vagoasdf Vagoasdf requested review from lucanovera and removed request for a team March 17, 2026 14:42
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 17, 2026

Greptile Summary

This PR records the SaaS integration config version (saas_version) on every ExecutionLog entry, making it easier to trace which version of an integration was running during a DSR execution. The change is well-scoped: a nullable Alembic migration, a model column, schema additions, a union-query update in the endpoint, and a new "Version" column in the admin UI event log table.

Key changes:

  • New nullable saas_version column added to the executionlog table via Alembic migration
  • GraphTask.__init__ extracts the version from the connector's raw saas_config dict at construction time and stamps it on every update_status call
  • log_start and log_retry logger messages also include the version when available
  • Admin UI EventLog table shows a versioned Tag when saas_version is present, or a - dash for non-SaaS connectors
  • The migration filename carries an xx_ placeholder prefix that is inconsistent with every other migration file in the repository (which use the hex revision hash as a prefix)
  • Two new model-layer tests call execution_log.delete(db) at the end, which is an unnecessary anti-pattern since the database is automatically cleared between test runs
  • One graph task test directly asserts on the private _saas_version attribute, which is fragile and redundant

Confidence Score: 4/5

  • Safe to merge after addressing the migration filename placeholder and the minor test clean-up issues.
  • The feature logic is correct and well-tested end-to-end. The only issues are cosmetic/convention-level: the migration file's xx_ prefix needs to be renamed, a couple of tests have unnecessary manual record deletions, and one test accesses a private attribute. None of these would cause a runtime failure.
  • The migration file xx_2026_03_11_0000_a1ca9ddf3c3c_add_saas_version_to_executionlog.py needs to be renamed to drop the xx_ placeholder prefix before merging.

Important Files Changed

Filename Overview
src/fides/api/alembic/migrations/versions/xx_2026_03_11_0000_a1ca9ddf3c3c_add_saas_version_to_executionlog.py Adds a nullable saas_version column to the executionlog table; migration logic is correct but the xx_ filename prefix is a placeholder that should be renamed to match the repo's hex-hash naming convention.
src/fides/api/task/graph_task.py Reads saas_config["version"] from the connector's raw dict at construction time and passes _saas_version into every update_status call and the log_start/log_retry logger messages. Logic is sound and handles None safely.
src/fides/api/v1/endpoints/privacy_request_endpoints.py Adds ExecutionLog.saas_version to the execution log query and null().label("saas_version") to the audit log query so the union remains column-aligned. No issues found.
clients/admin-ui/src/features/privacy-requests/events-and-logs/EventLog.tsx Adds a "Version" column and <Td> cell that renders the version as a tag or a dash placeholder, only shown when there are dataset entries and not in the request-finished view. No issues found.
tests/ops/models/privacy_request/test_execution_logs.py Adds two new unit tests for saas_version persistence; both unnecessarily call execution_log.delete(db) at the end, which is an established anti-pattern in this codebase since the DB is cleared automatically between runs.
tests/ops/task/test_graph_task.py Adds a saas_graph_task fixture and two integration tests; one test directly asserts on the private _saas_version attribute, which is fragile and redundant given the subsequent execution log assertion.

Last reviewed commit: 5ae13c1

Comment on lines +112 to +119
def test_execution_log_saas_version_stored(db, execution_log_data):
execution_log_data["saas_version"] = "2.3.0"
execution_log = ExecutionLog.create(db, data=execution_log_data)

retrieved = db.query(ExecutionLog).filter_by(privacy_request_id="test_id").first()
assert retrieved is not None
assert retrieved.saas_version == "2.3.0"
execution_log.delete(db)
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Manual record deletion in test — not needed

Both new tests call execution_log.delete(db) at the end. The database is automatically cleared between test runs, so this manual cleanup is unnecessary and goes against the testing conventions for this project. The cleanup should be removed from both new tests.

Suggested change
def test_execution_log_saas_version_stored(db, execution_log_data):
execution_log_data["saas_version"] = "2.3.0"
execution_log = ExecutionLog.create(db, data=execution_log_data)
retrieved = db.query(ExecutionLog).filter_by(privacy_request_id="test_id").first()
assert retrieved is not None
assert retrieved.saas_version == "2.3.0"
execution_log.delete(db)
def test_execution_log_saas_version_stored(db, execution_log_data):
execution_log_data["saas_version"] = "2.3.0"
ExecutionLog.create(db, data=execution_log_data)
retrieved = db.query(ExecutionLog).filter_by(privacy_request_id="test_id").first()
assert retrieved is not None
assert retrieved.saas_version == "2.3.0"

The same applies to test_execution_log_saas_version_null_for_non_saas at line 122.

Rule Used: Do not manually delete database records in test fi... (source)

Learnt From
ethyca/fides#6688

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 1219 to +1242

assert execution_log.status == ExecutionLogStatus.complete

def test_saas_version_null_for_non_saas_connector(
self, graph_task, db, privacy_request
):
"""Non-SaaS connectors (postgres in this fixture) should produce null saas_version."""
graph_task.log_start(action_type=ActionType.access)

execution_log = (
db.query(ExecutionLog)
.filter(
ExecutionLog.privacy_request_id == privacy_request.id,
ExecutionLog.collection_name == "b",
ExecutionLog.dataset_name == "a",
)
.first()
)
assert execution_log is not None
assert execution_log.saas_version is None

def test_saas_version_populated_for_saas_connector(
self, saas_graph_task, saas_example_connection_config, privacy_request, db
):
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Accessing private instance attribute in test

saas_graph_task._saas_version directly accesses a private implementation detail of GraphTask. This assertion is mostly redundant given that the test already verifies the saas_version is correctly propagated to the execution log record (the real observable behavior). The assertion on the private field is fragile — if the internal attribute is renamed or restructured it breaks without any functional regression.

Consider removing this assertion and relying solely on the execution log verification that follows, or exposing a public property if the attribute needs to be observable from outside the class.

Suggested change
assert execution_log.status == ExecutionLogStatus.complete
def test_saas_version_null_for_non_saas_connector(
self, graph_task, db, privacy_request
):
"""Non-SaaS connectors (postgres in this fixture) should produce null saas_version."""
graph_task.log_start(action_type=ActionType.access)
execution_log = (
db.query(ExecutionLog)
.filter(
ExecutionLog.privacy_request_id == privacy_request.id,
ExecutionLog.collection_name == "b",
ExecutionLog.dataset_name == "a",
)
.first()
)
assert execution_log is not None
assert execution_log.saas_version is None
def test_saas_version_populated_for_saas_connector(
self, saas_graph_task, saas_example_connection_config, privacy_request, db
):
def test_saas_version_populated_for_saas_connector(
self, saas_graph_task, saas_example_connection_config, privacy_request, db
):
"""SaaS connectors should stamp saas_version on every execution log entry."""
expected_version = saas_example_connection_config.saas_config["version"]
saas_graph_task.log_start(action_type=ActionType.access)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Vagoasdf and others added 6 commits March 17, 2026 12:44
- Use conditional logger.info calls instead of mixing f-strings with loguru placeholders in log_start/log_retry
- Add comment explaining _saas_version is snapshotted at construction time
- Fix missing blank line between test functions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Collaborator

@johnewart johnewart left a comment

Choose a reason for hiding this comment

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

The backend stuff looks good - the frontend bits seem sane but I will let someone else confirm that 👍🏼

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.

2 participants