Skip to content

CI: Update and improve database image build workflow#172

Draft
Marty-Byrde wants to merge 5 commits into
canaryfrom
ci/externalize-database-image-generation-workflow
Draft

CI: Update and improve database image build workflow#172
Marty-Byrde wants to merge 5 commits into
canaryfrom
ci/externalize-database-image-generation-workflow

Conversation

@Marty-Byrde

@Marty-Byrde Marty-Byrde commented Oct 29, 2025

Copy link
Copy Markdown
Member

Note

The idea of this pull request is to both reduce code duplication within the build-database-image workflows. At the same time the workflows aims to update the usage of the knowledgecheckr-database image based on the current branch-name.

This means that when the database-schema is changed on a new feature-branch --> a new docker-image is created. This image should then be used for all workflows that are executed on that branch. This way the code stays in sync with the database, e.g. when the schema was modified and the respective queries, but the new database-image is not used could cause errors.

Similarly, when a such a feature-branch is merged into the canary or main branch, the build-docker-image workflow will be triggered as well. I these cases all workflows should use either the canary or stable tag to use the most up-to-date and robust image.

Summary

  • Chores
    • Introduced a new reusable CI action to detect file changes and replaced inline diff scripts with this action across workflows.
    • Updated workflows to use the action for schema/file-change detection and renamed related steps to "Check for Schema Changes".
    • Adjusted workflow outputs to consume the action's standardized change indicator for more consistent CI behavior.

Summary by CodeRabbit

  • Chores
    • Introduced a centralized file change detection mechanism for CI/CD workflows to improve consistency and maintainability.
    • Enhanced automated schema change detection across deployment pipelines.
    • Strengthened image versioning logic to ensure reliable version management on primary branches.

This action is a reworked, improved and more generic version of the already existing check-changed-files action. It essentially checks whether the files that were changed within a commit-range match a given regex-pattern.
This way the checking of whether or not the database schema has been changed is done by the composite-action, reducing code duplication.
@coderabbitai

coderabbitai Bot commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a reusable composite GitHub Action at .github/actions/file-change/action.yml to detect file changes by regex between commits, and updates workflows and an existing action to use it; action exposes a changed boolean, supports skip and initial-commit handling. (≤50 words)

Changes

Cohort / File(s) Summary
New file-change action
.github/actions/file-change/action.yml
Adds composite action "Check for File Change" that accepts base_commit, newest_commit, regex_pattern, consider_initial_commit_relevant, and skip; computes git diff between commits, filters by regex to produce MATCHED_FILES, handles initial-commit and skip overrides, and exposes changed output.
Workflow changes — build DB image
.github/workflows/build-db-docker-image.yml
Replaces inline bash diff step with the new file-change action (regex drizzle/*/schema.ts), renames step to "Check for Schema Changes", and updates job output binding to use steps.changed.outputs.changed.
Workflow changes — semantic versioning
.github/workflows/semantic-versioning.yml
Replaces inline init.sql diff logic with the file-change action in schema-related stages, renames detection steps to "Check for Schema Changes", and consumes the action's changed output instead of custom script outputs; minor step-name formatting adjustments.
Compute tags action changes
.github/actions/compute-db-image-tags/action.yml
Alters tagging logic: main/canary failure paths now exit with error (remove implicit SHA/stable/latest tags on failure), and feature-branch flow still adds BRANCH-SHA_SHORT and now also adds a latest tag (with a noted caveat).

Sequence Diagram(s)

sequenceDiagram
    participant Workflow
    participant FileChangeAction as "file-change Action"
    participant Git

    Workflow->>FileChangeAction: call(base_commit, newest_commit, regex_pattern, skip, consider_initial_commit_relevant)
    alt consider_initial_commit_relevant && base_commit empty/zero
        FileChangeAction->>FileChangeAction: set changed = true
    else
        FileChangeAction->>Git: git diff --name-only base_commit...newest_commit
        Git-->>FileChangeAction: list of changed files
        FileChangeAction->>FileChangeAction: filter list by regex_pattern => MATCHED_FILES
        alt MATCHED_FILES non-empty
            FileChangeAction->>FileChangeAction: set changed = true
        else
            FileChangeAction->>FileChangeAction: set changed = false
        end
    end
    alt skip == 1 or true
        FileChangeAction->>FileChangeAction: override changed = true
    end
    FileChangeAction-->>Workflow: output changed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Spot-check:
    • .github/actions/file-change/action.yml: input validation, defaults, and output mapping correctness.
    • Shell script safety: set -euo pipefail, quoting, and git diff invocation (range vs three-dot usage).
    • Workflows: correct usage of steps.<id>.outputs.changed and step IDs matching action outputs.
    • .github/actions/compute-db-image-tags/action.yml: verify explicit exit paths and tagging semantics.

Possibly related PRs

Suggested labels

Code Improvements, released on @canary

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "CI: Update and improve database image build workflow" is clearly related to the main changes in the pull request. The changeset modifies CI workflows related to database image building, including creating a new reusable file-change action to reduce code duplication, updating multiple workflow files to use this action for schema change detection, and adjusting Docker image tagging logic. The title accurately refers to these changes affecting the database image build workflow, even though it uses somewhat generic language like "update and improve" rather than being highly specific about the refactoring and code duplication reduction that are core to the changeset.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ci/externalize-database-image-generation-workflow

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 035c5f8 and 5a58698.

📒 Files selected for processing (1)
  • .github/actions/compute-db-image-tags/action.yml (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Instrumented Build
  • GitHub Check: Production Build
🔇 Additional comments (2)
.github/actions/compute-db-image-tags/action.yml (2)

80-83: Major: "latest" tag on feature branches risks schema conflicts and non-deterministic behavior.

Line 82 adds a latest tag to all feature branches. The inline comment acknowledges that "other branches that use the latest db-image" may experience schema conflicts. This creates a race condition:

  • Multiple feature branches can push updates to the same latest tag.
  • Workflows on different branches may pull different schema versions from latest depending on timing.
  • If branch A modifies the schema and branch B doesn't, the latest tag becomes ambiguous.

Either remove the latest tag for feature branches, or implement branch-specific tagging (e.g., ${BRANCH}-latest) to prevent schema conflicts. The current approach contradicts the PR objective to "keep code and database schema in sync."


60-78: Critical: Exit 1 prevents outputs from being set; outputs will be undefined on main/canary branches.

When HEAD_TAG validation fails on main or canary branches, exit 1 is called (lines 67, 77) before the output section runs (lines 86–92). This means:

  • The warning output is never set (the WARNING variable is assigned but not output).
  • The tags output is empty or undefined, causing downstream steps that consume ${{ steps.out.outputs.tags }} to fail or behave unexpectedly.
  • Workflows will fail with an unclear error message instead of the intended graceful warning.

Verify this is intentional. If the goal is to enforce strict semantic versioning on main/canary, the action should still output tags and warning before exiting. Alternatively, consider a soft-fail with a fallback tag strategy.

Warning

Tools execution failed with the following error:

Failed to run tools: 14 UNAVAILABLE: read ECONNRESET


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Marty-Byrde Marty-Byrde changed the title Merge Feature Branch into Canary CI: Update and improve database image build workflow Oct 29, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/semantic-versioning.yml (1)

143-162: Output reference mismatch: accessing non-existent step output.

The schema-modified job output at line 147 references steps.changed.outputs.db_changed, but the file-change action only outputs changed. This will cause the workflow to fail when downstream jobs try to reference this output.

Compare with .github/workflows/build-db-docker-image.yml line 18, which correctly maps the output: db_changed: ${{ steps.changed.outputs.changed }}.

  schema-modified:
    runs-on: ubuntu-latest
    name: "Check for Database Schema Update"
    outputs:
-      db_changed: ${{ steps.changed.outputs.db_changed }}
+      db_changed: ${{ steps.changed.outputs.changed }}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24a7000 and 0b0b6bb.

📒 Files selected for processing (3)
  • .github/actions/file-change/action.yml (1 hunks)
  • .github/workflows/build-db-docker-image.yml (1 hunks)
  • .github/workflows/semantic-versioning.yml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Production Build
  • GitHub Check: Instrumented Build
🔇 Additional comments (3)
.github/actions/file-change/action.yml (1)

23-51: Action logic is sound with proper edge-case handling.

The implementation correctly:

  • Treats new branches (empty or all-zero base_commit) as having changes
  • Safely handles grep with || true to avoid failure when no matches are found
  • Applies the skip override after the main logic
  • Outputs the result as a GitHub Actions-compatible string
.github/workflows/semantic-versioning.yml (1)

156-162: Step configuration aligns with new action interface.

The step now correctly uses the new file-change action with appropriate inputs (base_commit, newest_commit, regex_pattern) and the step id is properly set to changed for referencing outputs.

.github/workflows/build-db-docker-image.yml (1)

14-32: Output binding and action integration are correct.

The job correctly:

  • Maps the action's changed output to the job-level db_changed output (line 18)
  • Configures the file-change action with appropriate inputs including the regex pattern for schema files
  • Allows downstream jobs to reference this output consistently

All subsequent conditional checks throughout the workflow reference needs.schema-modified.outputs.db_changed, which aligns with this output definition.

Comment on lines +1 to +56
name: Check for File Change
description: 'Checks whether a commit has modified files that match a given regex pattern.'

inputs:
base_commit:
description: 'The base_commit commit to compare against. When left empty "" it will assume its a new branch or initial commit and set `changed` to true.'
required: true
newest_commit:
description: The newest commit that the base is compared against
default: ${{ github.sha }}
required: false
regex_pattern:
description: 'Used to determinate if a file was modified within the commit-range; when it matches the pattern'
required: true
skip:
description: 'When set to true, the action will always return changed=true'
default: '0'
required: false

runs:
using: 'composite'
steps:
- run: |
set -euo pipefail
# For a new branch or initial commit, treat as relevant
if [ "${{ inputs.base_commit }}" = "" ] || [ "${{ inputs.base_commit }}" = "0000000000000000000000000000000000000000" ]; then
echo "New branch or initial commit. Considering changes relevant."
echo "changed=true" >> $GITHUB_OUTPUT
else
CHANGED_FILES=$(git diff --name-only ${{ inputs.base_commit }} ${{ inputs.newest_commit || github.sha }})

printf "Changed files: \n%s\n\n" "$CHANGED_FILES"

MATCHED_FILES=$(printf '%s\n' "$CHANGED_FILES" | grep -E "${{ inputs.regex_pattern }}" || true)
if [ -n "$MATCHED_FILES" ]; then
echo "Files matching regex '${{ inputs.regex_pattern }}':"
printf '%s\n' "$MATCHED_FILES"
echo "File change(s) were detected. Setting output `changed` to true."
echo "changed=true" >> "$GITHUB_OUTPUT"
else
echo "No changes detected."
echo "changed=false" >> "$GITHUB_OUTPUT"
fi
fi

if [ "${{ inputs.skip }}" = "1" ] || [ "${{ inputs.skip }}" = "true" ]; then
echo "File matching has been overridden. Setting `changed` to true."
echo "changed=true" >> $GITHUB_OUTPUT
fi
shell: bash
id: check

outputs:
changed:
description: 'Whether relevant file changes were detected'
value: ${{ steps.check.outputs.changed }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Typos in input descriptions.

Lines 6 and 13 contain minor typos:

  • Line 6: "base_commit commit" should be "base_commit" (redundant word)
  • Line 13: "determinate" should be "determine"

These don't affect functionality but should be corrected for clarity.

-    description: 'The base_commit commit to compare against. When left empty "" it will assume its a new branch or initial commit and set `changed` to true.'
+    description: 'The base_commit to compare against. When left empty "" it will assume its a new branch or initial commit and set `changed` to true.'
-    description: 'Used to determinate if a file was modified within the commit-range; when it matches the pattern'
+    description: 'Used to determine if a file was modified within the commit-range; when it matches the pattern'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name: Check for File Change
description: 'Checks whether a commit has modified files that match a given regex pattern.'
inputs:
base_commit:
description: 'The base_commit commit to compare against. When left empty "" it will assume its a new branch or initial commit and set `changed` to true.'
required: true
newest_commit:
description: The newest commit that the base is compared against
default: ${{ github.sha }}
required: false
regex_pattern:
description: 'Used to determinate if a file was modified within the commit-range; when it matches the pattern'
required: true
skip:
description: 'When set to true, the action will always return changed=true'
default: '0'
required: false
runs:
using: 'composite'
steps:
- run: |
set -euo pipefail
# For a new branch or initial commit, treat as relevant
if [ "${{ inputs.base_commit }}" = "" ] || [ "${{ inputs.base_commit }}" = "0000000000000000000000000000000000000000" ]; then
echo "New branch or initial commit. Considering changes relevant."
echo "changed=true" >> $GITHUB_OUTPUT
else
CHANGED_FILES=$(git diff --name-only ${{ inputs.base_commit }} ${{ inputs.newest_commit || github.sha }})
printf "Changed files: \n%s\n\n" "$CHANGED_FILES"
MATCHED_FILES=$(printf '%s\n' "$CHANGED_FILES" | grep -E "${{ inputs.regex_pattern }}" || true)
if [ -n "$MATCHED_FILES" ]; then
echo "Files matching regex '${{ inputs.regex_pattern }}':"
printf '%s\n' "$MATCHED_FILES"
echo "File change(s) were detected. Setting output `changed` to true."
echo "changed=true" >> "$GITHUB_OUTPUT"
else
echo "No changes detected."
echo "changed=false" >> "$GITHUB_OUTPUT"
fi
fi
if [ "${{ inputs.skip }}" = "1" ] || [ "${{ inputs.skip }}" = "true" ]; then
echo "File matching has been overridden. Setting `changed` to true."
echo "changed=true" >> $GITHUB_OUTPUT
fi
shell: bash
id: check
outputs:
changed:
description: 'Whether relevant file changes were detected'
value: ${{ steps.check.outputs.changed }}
name: Check for File Change
description: 'Checks whether a commit has modified files that match a given regex pattern.'
inputs:
base_commit:
description: 'The base_commit to compare against. When left empty "" it will assume its a new branch or initial commit and set `changed` to true.'
required: true
newest_commit:
description: The newest commit that the base is compared against
default: ${{ github.sha }}
required: false
regex_pattern:
description: 'Used to determine if a file was modified within the commit-range; when it matches the pattern'
required: true
skip:
description: 'When set to true, the action will always return changed=true'
default: '0'
required: false
runs:
using: 'composite'
steps:
- run: |
set -euo pipefail
# For a new branch or initial commit, treat as relevant
if [ "${{ inputs.base_commit }}" = "" ] || [ "${{ inputs.base_commit }}" = "0000000000000000000000000000000000000000" ]; then
echo "New branch or initial commit. Considering changes relevant."
echo "changed=true" >> $GITHUB_OUTPUT
else
CHANGED_FILES=$(git diff --name-only ${{ inputs.base_commit }} ${{ inputs.newest_commit || github.sha }})
printf "Changed files: \n%s\n\n" "$CHANGED_FILES"
MATCHED_FILES=$(printf '%s\n' "$CHANGED_FILES" | grep -E "${{ inputs.regex_pattern }}" || true)
if [ -n "$MATCHED_FILES" ]; then
echo "Files matching regex '${{ inputs.regex_pattern }}':"
printf '%s\n' "$MATCHED_FILES"
echo "File change(s) were detected. Setting output `changed` to true."
echo "changed=true" >> "$GITHUB_OUTPUT"
else
echo "No changes detected."
echo "changed=false" >> "$GITHUB_OUTPUT"
fi
fi
if [ "${{ inputs.skip }}" = "1" ] || [ "${{ inputs.skip }}" = "true" ]; then
echo "File matching has been overridden. Setting `changed` to true."
echo "changed=true" >> $GITHUB_OUTPUT
fi
shell: bash
id: check
outputs:
changed:
description: 'Whether relevant file changes were detected'
value: ${{ steps.check.outputs.changed }}
🤖 Prompt for AI Agents
In .github/actions/file-change/action.yml around lines 1 to 56, there are two
minor typos in the inputs descriptions: remove the redundant word in the
base_commit description so it reads "The base_commit to compare against..."
instead of "The base_commit commit to compare against", and change "determinate"
to "determine" in the regex_pattern description; update those strings
accordingly to correct the wording and save the file.

By adding the `consider_initial_commit_relevant` input one can specify whether the initial commit to a branch is considered as a change or not.
@codecov

codecov Bot commented Oct 29, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Marty-Byrde Marty-Byrde moved this to In progress in KnowledgeCheckr Project Oct 31, 2025
The reason for the removal of fallback-tags for the main and canary branch, when there are no available tags, is that the existence of tags is required. Hence, in case there are none an error should be displayed instead of following the branch-tag format
The reason for this is that this way the current implementation of initializing the respective database service works. Unless a new image is published while the code-changes that were made along side the schema changes are not merged.
@Marty-Byrde Marty-Byrde marked this pull request as draft November 9, 2025 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

1 participant