<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aditya Ranjan</title>
    <description>The latest articles on DEV Community by Aditya Ranjan (@adiranjan25).</description>
    <link>https://dev.to/adiranjan25</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4172456%2F8bef8682-b244-45de-bf95-0a7520a90e3c.png</url>
      <title>DEV Community: Aditya Ranjan</title>
      <link>https://dev.to/adiranjan25</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adiranjan25"/>
    <language>en</language>
    <item>
      <title>Automating Data Quality Checks in GitHub Actions with DataGuard AI</title>
      <dc:creator>Aditya Ranjan</dc:creator>
      <pubDate>Fri, 09 Oct 2026 04:50:08 +0000</pubDate>
      <link>https://dev.to/adiranjan25/automating-data-quality-checks-in-github-actions-with-dataguard-ai-57mh</link>
      <guid>https://dev.to/adiranjan25/automating-data-quality-checks-in-github-actions-with-dataguard-ai-57mh</guid>
      <description>&lt;p&gt;Hi,&lt;/p&gt;

&lt;p&gt;I've recently released DataGuard AI, an open-source Python toolkit for data quality and governance checks.&lt;/p&gt;

&lt;p&gt;I'm looking for a few developers willing to test the project and share independent technical feedback.&lt;/p&gt;

&lt;p&gt;It takes only a few minutes to install and run the sample demo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;dataguard-ai&lt;span class="o"&gt;==&lt;/span&gt;0.2.1
dataguard demo &lt;span class="nt"&gt;--rows&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd appreciate feedback on usability, detection accuracy, reporting, or any bugs you encounter.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/adiranjan25/dataguard-ai" rel="noopener noreferrer"&gt;https://github.com/adiranjan25/dataguard-ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tutorial: &lt;a href="https://dev.to/adiranjan25/automating-data-quality-checks-in-github-actions-with-dataguard-ai-5bfm"&gt;https://dev.to/adiranjan25/automating-data-quality-checks-in-github-actions-with-dataguard-ai-5bfm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have time to try it, feel free to share your findings through GitHub Issues or Discussions.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>github</category>
    </item>
    <item>
      <title>Automating Data Quality Checks in GitHub Actions with DataGuard AI</title>
      <dc:creator>Aditya Ranjan</dc:creator>
      <pubDate>Fri, 09 Oct 2026 04:34:22 +0000</pubDate>
      <link>https://dev.to/adiranjan25/automating-data-quality-checks-in-github-actions-with-dataguard-ai-5bfm</link>
      <guid>https://dev.to/adiranjan25/automating-data-quality-checks-in-github-actions-with-dataguard-ai-5bfm</guid>
      <description>&lt;h1&gt;
  
  
  Automating Data Quality Checks in GitHub Actions with DataGuard AI
&lt;/h1&gt;

&lt;p&gt;Data quality problems rarely wait until a convenient time to appear. A missing customer identifier, an unexpected null value, or a negative transaction amount can move through an ETL pipeline and affect downstream reports before anyone notices.&lt;/p&gt;

&lt;p&gt;One practical way to catch these issues earlier is to make data quality checks part of the development workflow.&lt;/p&gt;

&lt;p&gt;In this tutorial, I'll show how to use &lt;strong&gt;DataGuard AI&lt;/strong&gt;, an open-source Python data quality and governance toolkit, to scan sample data automatically using GitHub Actions.&lt;/p&gt;

&lt;p&gt;The objective is straightforward: every time code changes, run a data quality scan and generate reports developers can inspect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bring data quality into CI/CD?
&lt;/h2&gt;

&lt;p&gt;Software teams routinely automate unit tests, linting, and security checks. Data pipelines benefit from similar practices, especially when datasets and transformation logic evolve.&lt;/p&gt;

&lt;p&gt;Automated checks can help teams identify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing or invalid values&lt;/li&gt;
&lt;li&gt;Duplicate identifiers&lt;/li&gt;
&lt;li&gt;Unexpected data distributions&lt;/li&gt;
&lt;li&gt;Potentially sensitive information&lt;/li&gt;
&lt;li&gt;Violations of explicitly configured business rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These checks do not replace production monitoring, but they can catch problems earlier in the delivery process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing DataGuard AI
&lt;/h2&gt;

&lt;p&gt;DataGuard AI is an open-source Python toolkit that provides deterministic data quality checks, governance signals, configurable validation rules, and machine-readable reports.&lt;/p&gt;

&lt;p&gt;It supports CSV and JSON files, optional Parquet support, DuckDB, and PostgreSQL.&lt;/p&gt;

&lt;p&gt;AI-assisted explanations are optional. The core scanning functionality does not require an LLM or an API key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/adiranjan25/dataguard-ai" rel="noopener noreferrer"&gt;https://github.com/adiranjan25/dataguard-ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PyPI:&lt;/strong&gt; &lt;a href="https://pypi.org/project/dataguard-ai/" rel="noopener noreferrer"&gt;https://pypi.org/project/dataguard-ai/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install DataGuard AI
&lt;/h2&gt;

&lt;p&gt;You need Python 3.10 or newer.&lt;/p&gt;

&lt;p&gt;Install the public beta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;dataguard-ai&lt;span class="o"&gt;==&lt;/span&gt;0.2.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try the built-in synthetic retail demonstration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dataguard demo &lt;span class="nt"&gt;--rows&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates synthetic retail datasets and scans them for data quality and governance risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Prepare sample data
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;customers.csv&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;customer_id,name,email,age
101,Alice,alice@example.com,29
102,Bob,,34
103,Carol,carol@example.com,41
104,David,david@example.com,-5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This intentionally includes a missing email address and an invalid negative age.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;dataguard.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;max_null_pct&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;not_null&lt;/span&gt;
    &lt;span class="na"&gt;column&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer_id&lt;/span&gt;
    &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CRITICAL&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;not_null&lt;/span&gt;
    &lt;span class="na"&gt;column&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;email&lt;/span&gt;
    &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HIGH&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;between&lt;/span&gt;
    &lt;span class="na"&gt;column&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;age&lt;/span&gt;
    &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120&lt;/span&gt;
    &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HIGH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These rules express a simple dataset contract: customer identifiers and email addresses must be present, and age must fall within a reasonable range.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Run a local scan
&lt;/h2&gt;

&lt;p&gt;Execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dataguard scan customers.csv &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--config&lt;/span&gt; dataguard.yml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--json-out&lt;/span&gt; report.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--html-out&lt;/span&gt; report.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DataGuard AI will inspect the dataset and write two reports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;report.json&lt;/code&gt; — structured findings suitable for automation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;report.html&lt;/code&gt; — a human-readable report for reviewing findings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the sample data deliberately contains invalid values, you should expect findings related to missing email data and the age range rule.&lt;/p&gt;

&lt;p&gt;The exact severity, scores, and other findings depend on the tool's configuration and detection behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Automate scanning with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Create this file in your repository:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.github/workflows/data-quality.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Data Quality Checks&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data-quality&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v5&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.12"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install DataGuard AI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python -m pip install dataguard-ai==0.2.1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scan customer data&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;dataguard scan customers.csv \&lt;/span&gt;
            &lt;span class="s"&gt;--config dataguard.yml \&lt;/span&gt;
            &lt;span class="s"&gt;--json-out report.json \&lt;/span&gt;
            &lt;span class="s"&gt;--html-out report.html&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload reports&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always()&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dataguard-quality-report&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;report.json&lt;/span&gt;
            &lt;span class="s"&gt;report.html&lt;/span&gt;
          &lt;span class="na"&gt;if-no-files-found&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;warn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when someone pushes changes to &lt;code&gt;main&lt;/code&gt; or opens a pull request, GitHub Actions runs the scanner and uploads the generated reports.&lt;/p&gt;

&lt;p&gt;Developers can open the workflow run, find its artifacts, and download the reports for review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important limitation:&lt;/strong&gt; DataGuard AI v0.2.1 generates findings, but the workflow above does not automatically fail merely because a quality issue is detected. The scan step succeeds if execution and report generation succeed. Enforcing a quality gate requires an additional policy step that evaluates the JSON report against agreed thresholds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Review the findings
&lt;/h2&gt;

&lt;p&gt;The HTML report provides an accessible way to inspect quality and governance scores, affected columns, severity, and suggested remediation.&lt;/p&gt;

&lt;p&gt;The JSON report is more suitable for downstream automation, such as quality dashboards, policy evaluation, or custom CI checks.&lt;/p&gt;

&lt;p&gt;This separation is useful because different teams need different levels of detail: engineers may want structured output, while reviewers may prefer a visual summary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this approach fits
&lt;/h2&gt;

&lt;p&gt;This pattern can be useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data engineering repositories containing sample or test datasets&lt;/li&gt;
&lt;li&gt;ETL development and transformation validation&lt;/li&gt;
&lt;li&gt;Data contract experimentation&lt;/li&gt;
&lt;li&gt;Governance checks during development&lt;/li&gt;
&lt;li&gt;CI/CD demonstrations and training&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For large production datasets, teams should evaluate scanning cost, data sensitivity, execution environment, and performance before adopting the same approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Data quality should not begin only after a pipeline reaches production.&lt;/p&gt;

&lt;p&gt;By integrating lightweight, reproducible checks into GitHub Actions, engineering teams can make quality risks visible earlier and establish a foundation for stronger data delivery practices.&lt;/p&gt;

&lt;p&gt;DataGuard AI is still a public beta, and community feedback is welcome.&lt;/p&gt;

&lt;p&gt;If you work with Python, ETL, data governance, or CI/CD, I'd appreciate your feedback on the installation experience, validation capabilities, and opportunities for improvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explore the source code:&lt;/strong&gt; &lt;a href="https://github.com/adiranjan25/dataguard-ai" rel="noopener noreferrer"&gt;https://github.com/adiranjan25/dataguard-ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install from PyPI:&lt;/strong&gt; &lt;a href="https://pypi.org/project/dataguard-ai/" rel="noopener noreferrer"&gt;https://pypi.org/project/dataguard-ai/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contribute or report an issue:&lt;/strong&gt; &lt;a href="https://github.com/adiranjan25/dataguard-ai/issues" rel="noopener noreferrer"&gt;https://github.com/adiranjan25/dataguard-ai/issues&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>ai</category>
      <category>git</category>
    </item>
  </channel>
</rss>
