<?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: Thu Kha Kyawe</title>
    <description>The latest articles on DEV Community by Thu Kha Kyawe (@thukhakyawe_cloud).</description>
    <link>https://dev.to/thukhakyawe_cloud</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%2F3601335%2Fd44a63a0-36bb-4c80-a1f0-1d55fd8ccc1c.png</url>
      <title>DEV Community: Thu Kha Kyawe</title>
      <link>https://dev.to/thukhakyawe_cloud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thukhakyawe_cloud"/>
    <language>en</language>
    <item>
      <title>Day 19: Complete a Production DVC Pipeline with SeaweedFS Remote</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Sun, 19 Jul 2026 05:10:53 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/day-19-complete-a-production-dvc-pipeline-with-seaweedfs-remote-17k9</link>
      <guid>https://dev.to/thukhakyawe_cloud/day-19-complete-a-production-dvc-pipeline-with-seaweedfs-remote-17k9</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;Complete the xFusionCorp Industries fraud-detection production DVC pipeline. Three stages are already wired in dvc.yaml, two remain, and the pipeline must finish as a reproducible, SeaweedFS-backed, v1.0-tagged release.&lt;/p&gt;

&lt;p&gt;A project exists at /root/code/ml-pipeline/ with Git and DVC initialised. The params.yaml is in place and the .dvc/config is pre-configured to push to the SeaweedFS bucket dvc-storage at &lt;a href="http://localhost:8333" rel="noopener noreferrer"&gt;http://localhost:8333&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The ingest, validate, and preprocess stages are already declared in dvc.yaml, but one of them is misconfigured and prevents dvc repro from completing — run dvc repro to see it fail. The two scripts for the remaining stages are pre-staged at /root/code/ml-pipeline/scripts-staging/train.py and scripts-staging/evaluate.py, and belong in scripts/.&lt;/p&gt;

&lt;p&gt;Acceptance criteria:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The misconfigured existing stage is corrected so dvc repro can complete.
Two further stages are declared in dvc.yaml:
    train – Depends on the preprocessed dataset and scripts/train.py; reads n_estimators, max_depth, test_size, and random_seed from params.yaml; outputs models/model.pkl and data/processed/test_split.csv; declares metrics.json as a DVC metric with cache: false.
    evaluate – Depends on models/model.pkl, data/processed/test_split.csv, and scripts/evaluate.py; outputs reports/evaluation.json declared with cache: false.
The full pipeline has been reproduced, the cache pushed to the SeaweedFS remote, and the current state tagged v1.0.
Every change is committed to Git so the release is fully captured.

Open the SeaweedFS Filer button at the top of the lab and navigate to /buckets/dvc-storage/ to confirm that the bucket holds the pushed artefacts under the files/md5/... layout.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Step 1: Enter the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/code/ml-pipeline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Run the pipeline once&lt;/p&gt;

&lt;p&gt;The lab tells you one stage is intentionally broken.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't fix anything yet.&lt;/p&gt;

&lt;p&gt;Read the error carefully.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;p&gt;Missing dependency&lt;br&gt;
Output mismatch&lt;br&gt;
Script not found&lt;br&gt;
Wrong filename&lt;/p&gt;

&lt;p&gt;The error will tell you exactly which existing stage is misconfigured.&lt;/p&gt;

&lt;p&gt;Step 3: Inspect the existing pipeline&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="s"&gt;cat dvc.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&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="s"&gt;root@controlplane ml-pipeline on  main [?] ✖ cat dvc.yaml&lt;/span&gt;
&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ingest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 scripts/ingest.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;scripts/ingest.py&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/raw/data.csv&lt;/span&gt;

  &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 scripts/validate.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/raw/data.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;scripts/validate.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;reports/validation.json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="na"&gt;preprocess&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 scripts/preprocess.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/raw/data.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;scripts/preprocess.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/cleaned.csv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Check what preprocess.py actually created&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; data/processed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane ml-pipeline on  main [?] ➜  ls -l data/processed
total 4
-rw-r--r-- 1 root root 702 Jul 19 00:15 clean.csv
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Fix the preprocess output path.&lt;/p&gt;

&lt;p&gt;Open dvc.yaml in the VS Code editor. In the preprocess stage, change the last line from:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - data/processed/cleaned.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - data/processed/clean.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save the file (Ctrl+S).&lt;/p&gt;

&lt;p&gt;Step 6: Copy the remaining scripts into scripts/.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;scripts-staging/train.py    scripts/train.py
&lt;span class="nb"&gt;cp &lt;/span&gt;scripts-staging/evaluate.py scripts/evaluate.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the train and evaluate stages to dvc.yaml.&lt;/p&gt;

&lt;p&gt;Step 7: Declare the train and evaluate stages with dvc stage add.&lt;/p&gt;

&lt;p&gt;Train stage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc stage add &lt;span class="nt"&gt;-n&lt;/span&gt; train &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; data/processed/clean.csv &lt;span class="nt"&gt;-d&lt;/span&gt; scripts/train.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; n_estimators,max_depth,test_size,random_seed &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; models/model.pkl &lt;span class="nt"&gt;-o&lt;/span&gt; data/processed/test_split.csv &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-M&lt;/span&gt; metrics.json &lt;span class="se"&gt;\&lt;/span&gt;
  python3 scripts/train.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Evaluate stage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc stage add &lt;span class="nt"&gt;-n&lt;/span&gt; evaluate &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; models/model.pkl &lt;span class="nt"&gt;-d&lt;/span&gt; data/processed/test_split.csv &lt;span class="nt"&gt;-d&lt;/span&gt; scripts/evaluate.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-O&lt;/span&gt; reports/evaluation.json &lt;span class="se"&gt;\&lt;/span&gt;
  python3 scripts/evaluate.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push to SeaweedFS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Complete production DVC pipeline"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tag the release:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag v1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 8: Verify the SeaweedFS bucket&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpro1uix69mf8zbfe1qm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpro1uix69mf8zbfe1qm1.png" alt=" " width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanation (Beginner Friendly)&lt;/p&gt;

&lt;p&gt;In this lab, the ingest and validate stages completed successfully, but the pipeline stopped during the preprocess stage.&lt;/p&gt;

&lt;p&gt;When you ran:&lt;/p&gt;

&lt;p&gt;dvc repro&lt;/p&gt;

&lt;p&gt;DVC executed the preprocess.py script successfully, and the script printed:&lt;/p&gt;

&lt;p&gt;Preprocessed: 20 clean rows&lt;/p&gt;

&lt;p&gt;However, DVC then displayed the following error:&lt;/p&gt;

&lt;p&gt;ERROR: failed to reproduce 'preprocess':&lt;br&gt;
output 'data/processed/cleaned.csv' does not exist&lt;/p&gt;

&lt;p&gt;This tells us that the Python script itself did not fail. Instead, DVC could not find the output file that was defined in dvc.yaml.&lt;/p&gt;

&lt;p&gt;To investigate, we opened the pipeline configuration:&lt;/p&gt;

&lt;p&gt;cat dvc.yaml&lt;/p&gt;

&lt;p&gt;Inside the preprocess stage, the output was configured as:&lt;/p&gt;

&lt;p&gt;outs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data/processed/cleaned.csv&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, we checked the actual contents of the data/processed directory:&lt;/p&gt;

&lt;p&gt;ls -l data/processed&lt;/p&gt;

&lt;p&gt;The output showed:&lt;/p&gt;

&lt;p&gt;clean.csv&lt;/p&gt;

&lt;p&gt;This revealed the problem: the script created clean.csv, but dvc.yaml expected cleaned.csv.&lt;/p&gt;

&lt;p&gt;Because DVC verifies that every declared output exists after a stage finishes, it stopped the pipeline when it couldn't find cleaned.csv.&lt;/p&gt;

&lt;p&gt;To fix the issue, we updated the outs section of the preprocess stage so that it matched the file actually produced by the script:&lt;/p&gt;

&lt;p&gt;preprocess:&lt;br&gt;
  cmd: python3 scripts/preprocess.py&lt;br&gt;
  deps:&lt;br&gt;
    - data/raw/data.csv&lt;br&gt;
    - scripts/preprocess.py&lt;br&gt;
  outs:&lt;br&gt;
    - data/processed/clean.csv&lt;/p&gt;

&lt;p&gt;After saving the change, running:&lt;/p&gt;

&lt;p&gt;dvc repro&lt;/p&gt;

&lt;p&gt;again allows DVC to locate the correct output file and continue executing the remaining stages of the pipeline.&lt;/p&gt;

&lt;p&gt;Key Takeaway&lt;/p&gt;

&lt;p&gt;A very common DVC error is:&lt;/p&gt;

&lt;p&gt;output '' does not exist&lt;/p&gt;

&lt;p&gt;When you see this message, the first thing to check is whether the output filename in dvc.yaml exactly matches the filename created by the script. Even a small difference—such as clean.csv versus cleaned.csv—is enough to cause the pipeline to fail. Always verify the actual output file (for example, using ls) before updating the pipeline configuration.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-MLOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>100daysofmlops</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>Day 18: Version Datasets and Models Across Git Branches</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Sun, 19 Jul 2026 05:04:56 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/day-18-version-datasets-and-models-across-git-branches-2c5c</link>
      <guid>https://dev.to/thukhakyawe_cloud/day-18-version-datasets-and-models-across-git-branches-2c5c</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;The xFusionCorp Industries MLOps team versions datasets and models on separate Git branches so it can reproduce and roll between versions cleanly. Tag the current state as v1.0, create a v2-improved branch built on a newer dataset (which retrains the model), and confirm that switching back restores the original data and model.&lt;/p&gt;

&lt;p&gt;A project exists at /root/code/fraud-detection/ with a working DVC pipeline (it processes the data and trains a model) and the baseline data/raw/transactions.csv already tracked.&lt;/p&gt;

&lt;p&gt;An improved dataset has been pre-staged at /root/code/fraud-detection/data/raw/transactions_v2.csv and is visible in the file explorer. Do not delete this file.&lt;/p&gt;

&lt;p&gt;Acceptance criteria:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On the main branch, the current state is tagged v1.0.
A branch named v2-improved holds the v2 state: the tracked dataset carries the contents of the v2 file (re-tracked with DVC), the pipeline has been re-run so models/model.pkl is retrained and versioned alongside the dataset, and the changes are committed.
Back on the main branch, the v1 dataset and model are restored on disk, matching the hashes recorded by the v1.0 tag.

The DVC extension's DVC TRACKED section in the EXPLORER panel reflects the tracked dataset and model for the branch you currently have checked out. To compare the exact hashes recorded on each branch, use git show &amp;lt;ref&amp;gt;:dvc.lock or dvc status.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;This is one of the most realistic DVC labs. You'll combine Git branches + DVC + pipeline reproducibility.&lt;/p&gt;

&lt;p&gt;Step 1: Go to the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/code/fraud-detection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Make sure everything is committed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;On branch main&lt;br&gt;
nothing to commit, working tree clean&lt;/p&gt;

&lt;p&gt;If not clean, commit your changes before continuing.&lt;/p&gt;

&lt;p&gt;Step 3: Tag the current version&lt;/p&gt;

&lt;p&gt;The lab requires the current main branch to be tagged as v1.0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag v1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;v1.0&lt;/p&gt;

&lt;p&gt;Step 4: Create the new branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; v2-improved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;v2-improved
main&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 5: Replace the tracked dataset with the new version&lt;/p&gt;

&lt;p&gt;The improved dataset already exists:&lt;/p&gt;

&lt;p&gt;data/raw/transactions_v2.csv&lt;/p&gt;

&lt;p&gt;Replace the original dataset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;data/raw/transactions_v2.csv data/raw/transactions.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 6: Update DVC tracking&lt;/p&gt;

&lt;p&gt;Since the tracked file changed, update the DVC metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc add data/raw/transactions.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This updates:&lt;/p&gt;

&lt;p&gt;transactions.csv.dvc&lt;br&gt;
DVC cache&lt;/p&gt;

&lt;p&gt;Step 7: Retrain the pipeline&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should rerun:&lt;/p&gt;

&lt;p&gt;process_data&lt;br&gt;
split_data&lt;br&gt;
train&lt;/p&gt;

&lt;p&gt;and regenerate:&lt;/p&gt;

&lt;p&gt;models/model.pkl&lt;br&gt;
metrics.json&lt;br&gt;
dvc.lock&lt;/p&gt;

&lt;p&gt;Step 8: Check Git status&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see changes similar to:&lt;/p&gt;

&lt;p&gt;modified: data/raw/transactions.csv.dvc&lt;br&gt;
modified: dvc.lock&lt;br&gt;
modified: metrics.json&lt;br&gt;
modified: models/model.pkl.dvc   (if model is DVC tracked)&lt;/p&gt;

&lt;p&gt;Note: The exact files may differ depending on how the lab repository is set up.&lt;/p&gt;

&lt;p&gt;Step 9: Commit the v2 state&lt;/p&gt;

&lt;p&gt;Stage everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Update dataset to v2 and retrain model"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 10: Return to main&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 11: Restore the DVC-tracked files&lt;/p&gt;

&lt;p&gt;After switching branches, restore the correct dataset and model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc checkout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 12: Verify&lt;/p&gt;

&lt;p&gt;Check the dataset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;md5sum &lt;/span&gt;data/raw/transactions.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; models/model.pkl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify DVC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;Data and pipelines are up to date.&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanation (Beginner Friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why do we create a Git tag?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The command:&lt;/p&gt;

&lt;p&gt;git tag v1.0&lt;/p&gt;

&lt;p&gt;creates a permanent label for the current project state.&lt;/p&gt;

&lt;p&gt;Think of it as taking a snapshot:&lt;/p&gt;

&lt;p&gt;main&lt;br&gt;
 │&lt;br&gt;
 ├── v1.0  ← Snapshot&lt;/p&gt;

&lt;p&gt;You can always return to exactly this version later.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why create a new branch?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of changing the main branch directly, we create:&lt;/p&gt;

&lt;p&gt;v2-improved&lt;/p&gt;

&lt;p&gt;This allows us to safely experiment with a new dataset.&lt;/p&gt;

&lt;p&gt;The structure becomes:&lt;/p&gt;

&lt;p&gt;main&lt;br&gt;
 │&lt;br&gt;
 └── v2-improved&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why run dvc add again?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The file name stays the same:&lt;/p&gt;

&lt;p&gt;transactions.csv&lt;/p&gt;

&lt;p&gt;but its contents change because you copied in the improved dataset.&lt;/p&gt;

&lt;p&gt;DVC tracks file contents (using hashes), not just filenames.&lt;/p&gt;

&lt;p&gt;Running:&lt;/p&gt;

&lt;p&gt;dvc add data/raw/transactions.csv&lt;/p&gt;

&lt;p&gt;updates the .dvc pointer to reference the new dataset version.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why rerun the pipeline?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dataset changed.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;p&gt;transactions.csv&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
process_data&lt;br&gt;
        ▼&lt;br&gt;
split_data&lt;br&gt;
        ▼&lt;br&gt;
train&lt;br&gt;
        ▼&lt;br&gt;
model.pkl&lt;/p&gt;

&lt;p&gt;Every downstream stage depends on the dataset, so DVC reruns the pipeline to produce a model trained on the new data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use dvc checkout?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you switch back to:&lt;/p&gt;

&lt;p&gt;git checkout main&lt;/p&gt;

&lt;p&gt;Git restores:&lt;/p&gt;

&lt;p&gt;dvc.yaml&lt;br&gt;
.dvc files&lt;br&gt;
dvc.lock&lt;/p&gt;

&lt;p&gt;However, Git does not restore the actual dataset or model, because DVC manages those files.&lt;/p&gt;

&lt;p&gt;Running:&lt;/p&gt;

&lt;p&gt;dvc checkout&lt;/p&gt;

&lt;p&gt;reads the .dvc files and restores the correct versions of:&lt;/p&gt;

&lt;p&gt;transactions.csv&lt;br&gt;
model.pkl&lt;/p&gt;

&lt;p&gt;from the DVC cache.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-MLOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>100daysofmlops</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>Day 17: Run and Compare DVC Experiments</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Sun, 19 Jul 2026 05:01:39 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/day-17-run-and-compare-dvc-experiments-a97</link>
      <guid>https://dev.to/thukhakyawe_cloud/day-17-run-and-compare-dvc-experiments-a97</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;The xFusionCorp Industries MLOps team needs every model training run to be reproducible, automatically tracked, and easy to compare so a chosen configuration can be promoted into version control. The fraud-detection pipeline is parameterized by max_depth, currently set shallow enough to underfit. Using DVC experiments, run three tracked experiments over different max_depth values, compare their recorded f1_score on the held-out test set, and promote the best-scoring run so its parameters, metrics, and model become the tracked workspace state.&lt;/p&gt;

&lt;p&gt;A project exists at /root/code/fraud-detection/ with a parameterised DVC pipeline already in place. params.yaml declares n_estimators: 100 and max_depth: 4, and the baseline pipeline has been run once. src/models/train.py reads both parameters, trains the model, and evaluates it on the held-out test set, writing the real accuracy and f1_score to metrics.json. Do not modify the Python files.&lt;/p&gt;

&lt;p&gt;Acceptance criteria:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Three DVC experiments have been run, each with a different value for max_depth across a reasonable range (for example 2, 6, and 12); each experiment retrains the model and produces a fresh metrics.json.
The experiment with the highest f1_score is applied to the workspace, so its max_depth, metrics.json, and models/model.pkl become the tracked state.

The DVC extension's EXPERIMENTS view (open the DVC panel from the Activity Bar) lists every experiment alongside its parameters and metrics, which is a convenient way to compare runs at a glance.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;This lab introduces DVC Experiments (dvc exp), which let you test different parameter values without committing changes to Git.&lt;/p&gt;

&lt;p&gt;Step 1: Move into the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/code/fraud-detection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Verify the current parameter&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="s"&gt;cat params.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;n_estimators: 100&lt;br&gt;
max_depth: 4&lt;/p&gt;

&lt;p&gt;Step 3: Run the first experiment (max_depth=2)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc exp run &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nv"&gt;max_depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will:&lt;/p&gt;

&lt;p&gt;Update max_depth to 2 for the experiment.&lt;br&gt;
Retrain the model.&lt;br&gt;
Generate a new metrics.json.&lt;br&gt;
Save the experiment in DVC (without changing your Git history).&lt;/p&gt;

&lt;p&gt;Step 4: Run the second experiment (max_depth=6)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc exp run &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nv"&gt;max_depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Run the third experiment (max_depth=12)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc exp run &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nv"&gt;max_depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have three experiments, each using a different max_depth.&lt;/p&gt;

&lt;p&gt;Step 6: Compare the experiments &lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; less
dvc exp show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;root@controlplane fraud-detection on  main [!] ➜  dvc exp show&lt;br&gt;
 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&amp;gt;&lt;br&gt;
  Experiment                 Created    accuracy   f1_score   n_estimators   max_depth   data/processed/clean_transactions.csv   data/processed/&amp;gt;&lt;br&gt;
 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&amp;gt;&lt;br&gt;
  workspace                  -              0.75     0.6795   100            12          34832f8da536af18bb25236981b31c04        1d9e91ebeec0d17&amp;gt;&lt;br&gt;
  main                       09:37 AM       0.71     0.5735   100            4           34832f8da536af18bb25236981b31c04        1d9e91ebeec0d17&amp;gt;&lt;br&gt;
  ├── f75ec1a [lying-zigs]   09:46 AM       0.75     0.6795   100            12          34832f8da536af18bb25236981b31c04        1d9e91ebeec0d17&amp;gt;&lt;br&gt;
  ├── fad90d2 [erect-flap]   09:45 AM      0.745     0.6483   100            6           34832f8da536af18bb25236981b31c04        1d9e91ebeec0d17&amp;gt;&lt;br&gt;
  └── 422a560 [stone-leas]   09:45 AM        0.6     0.2453   100            2           34832f8da536af18bb25236981b31c04        1d9e91ebeec0d17&amp;gt;&lt;br&gt;
 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&amp;gt;&lt;/p&gt;

&lt;p&gt;Step 7: Identify the best experiment&lt;/p&gt;

&lt;p&gt;Look at the f1_score column.&lt;/p&gt;

&lt;p&gt;Find the experiment with the highest f1_score.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;exp-f75ec1a has the highest f1_score of 0.6795.&lt;/p&gt;

&lt;p&gt;Step 8: Apply the best experiment&lt;/p&gt;

&lt;p&gt;Apply it to your workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc exp apply &amp;lt;experiment-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main [!] ➜  dvc exp apply f75ec1a
Building workspace index                                                                                             |7.00 [00:00, 1.46kentry/s]
Comparing indexes                                                                                                    |8.00 [00:00, 4.61kentry/s]
Applying changes                                                                                                      |0.00 [00:00,     ?file/s]
Changes for experiment 'f75ec1a' have been applied to your current workspace.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This updates:&lt;/p&gt;

&lt;p&gt;params.yaml&lt;br&gt;
metrics.json&lt;br&gt;
models/model.pkl&lt;/p&gt;

&lt;p&gt;to match the selected experiment.&lt;/p&gt;

&lt;p&gt;Step 9: Verify the applied parameter&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="s"&gt;cat params.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main [!] ➜  cat params.yaml
n_estimators: 100
max_depth: 12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 10: Verify the metrics&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc metrics show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The displayed metrics should match the winning experiment.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main [!] ➜  dvc metrics show
Path          accuracy    f1_score
metrics.json  0.75        0.6795
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 11: Verify the model&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; models/model.pkl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model file should have been regenerated for the applied experiment.&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanation (Beginner Friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is a DVC Experiment?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normally, if you want to test a new model configuration, you would:&lt;/p&gt;

&lt;p&gt;Edit params.yaml.&lt;br&gt;
Run dvc repro.&lt;br&gt;
Record the results.&lt;br&gt;
Repeat.&lt;/p&gt;

&lt;p&gt;This becomes tedious and makes it hard to compare experiments.&lt;/p&gt;

&lt;p&gt;DVC Experiments automate this process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why run multiple experiments?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Different values of max_depth can affect model performance.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;max_depth = 2&lt;/p&gt;

&lt;p&gt;A very shallow tree may underfit the data.&lt;/p&gt;

&lt;p&gt;max_depth = 6&lt;/p&gt;

&lt;p&gt;May provide a good balance.&lt;/p&gt;

&lt;p&gt;max_depth = 12&lt;/p&gt;

&lt;p&gt;A deeper tree may overfit.&lt;/p&gt;

&lt;p&gt;The goal is to find the value that gives the best f1_score.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does dvc exp run do?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run:&lt;/p&gt;

&lt;p&gt;dvc exp run -S max_depth=6&lt;/p&gt;

&lt;p&gt;DVC temporarily changes:&lt;/p&gt;

&lt;p&gt;max_depth: 6&lt;/p&gt;

&lt;p&gt;runs the pipeline, records the metrics, and saves the results as a named experiment.&lt;/p&gt;

&lt;p&gt;Your Git history remains unchanged.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use dvc exp show?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of opening each metrics.json manually, DVC displays all experiments together.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;h2&gt;
  
  
  Experiment      max_depth    accuracy    f1_score
&lt;/h2&gt;

&lt;p&gt;exp-A               2          0.88        0.84&lt;br&gt;
exp-B               6          0.94        0.92&lt;br&gt;
exp-C              12          0.93        0.90&lt;/p&gt;

&lt;p&gt;This makes it easy to compare different parameter values.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does dvc exp apply do?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you've found the experiment with the highest f1_score, apply it:&lt;/p&gt;

&lt;p&gt;dvc exp apply exp-B&lt;/p&gt;

&lt;p&gt;This updates your workspace so that it reflects the best experiment:&lt;/p&gt;

&lt;p&gt;params.yaml uses the winning max_depth.&lt;br&gt;
metrics.json contains the winning metrics.&lt;br&gt;
models/model.pkl is the model trained with those parameters.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-MLOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>100daysofmlops</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>Day 16: Track ML Metrics with DVC</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Sun, 19 Jul 2026 04:57:28 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/day-16-track-ml-metrics-with-dvc-47m4</link>
      <guid>https://dev.to/thukhakyawe_cloud/day-16-track-ml-metrics-with-dvc-47m4</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;After training a model, the xFusionCorp Industries ML team requires DVC to surface model metrics through dvc metrics show. Although the fraud-detection pipeline successfully trains a model and generates a metrics.json file, DVC currently does not recognize this file as a metric. Ensure that the metrics.json file is properly configured to be recognized by DVC.&lt;/p&gt;

&lt;p&gt;A project exists at /root/code/fraud-detection/ with a three-stage DVC pipeline (process_data, split_data, train). The train stage runs src/models/train.py, which writes the model to models/model.pkl and metrics to metrics.json. Do not modify the Python files.&lt;/p&gt;

&lt;p&gt;Acceptance criteria:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The train stage in dvc.yaml declares metrics.json as a DVC metric output rather than a regular file output, with cache: false so the JSON lives in Git for diff history rather than in the DVC cache.
The pipeline has been reproduced so the metric registration takes effect, and dvc metrics show reports the accuracy and f1_score values from metrics.json.

Tip: once the metric is registered, dvc metrics diff compares its values across Git commits, which is useful when iterating on the model.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Step 1: Move into the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/code/fraud-detection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Inspect the current train stage&lt;/p&gt;

&lt;p&gt;Open dvc.yaml:&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="s"&gt;cat dvc.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that metrics.json is missing.&lt;/p&gt;

&lt;p&gt;Step 3: Modify the train stage&lt;/p&gt;

&lt;p&gt;Add a metrics section.&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;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;process_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/data/process_data.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/raw/transactions.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/data/process_data.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/clean_transactions.csv&lt;/span&gt;

  &lt;span class="na"&gt;split_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/data/split_data.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/clean_transactions.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/data/split_data.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/train.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/test.csv&lt;/span&gt;

  &lt;span class="na"&gt;train&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/models/train.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/train.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/models/train.py&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n_estimators&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;models/model.pkl&lt;/span&gt;
    &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;metrics.json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important: Do not put metrics.json under outs:. The lab specifically requires it to be declared as a metric with cache: false.&lt;/p&gt;

&lt;p&gt;Step 4: Save dvc.yaml and add params.yaml if it doesn't exist.&lt;/p&gt;

&lt;p&gt;Verify the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;dvc.yaml
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; params.yaml &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
n_estimators: 100
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Reproduce the pipeline&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This regenerates:&lt;/p&gt;

&lt;p&gt;models/model.pkl&lt;br&gt;
metrics.json&lt;br&gt;
dvc.lock&lt;/p&gt;

&lt;p&gt;Step 6: Verify the metric&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc metrics show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output will look similar to:&lt;/p&gt;

&lt;p&gt;Path          accuracy    f1_score&lt;br&gt;
metrics.json  1.0         1.0&lt;/p&gt;

&lt;p&gt;The exact values will vary.&lt;/p&gt;

&lt;p&gt;Step 7: Verify the metric file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;metrics.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "accuracy": 1.0,&lt;br&gt;
  "f1_score": 1.0&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Step 8: Verify dvc.lock&lt;/p&gt;

&lt;p&gt;(Optional)&lt;/p&gt;

&lt;p&gt;cat dvc.lock&lt;/p&gt;

&lt;p&gt;You should see metrics.json recorded under the train stage.&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanation (Beginner Friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is metrics.json?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After training the model, the Python script creates a file called:&lt;/p&gt;

&lt;p&gt;metrics.json&lt;/p&gt;

&lt;p&gt;It contains information about how well the model performed.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "accuracy": 1.0,&lt;br&gt;
  "f1_score": 1.0&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;These numbers help you evaluate the model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why doesn't DVC recognize it automatically?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DVC only knows about files that are declared in dvc.yaml.&lt;/p&gt;

&lt;p&gt;Currently, DVC knows about:&lt;/p&gt;

&lt;p&gt;input files (deps)&lt;br&gt;
output files (outs)&lt;br&gt;
parameters (params)&lt;/p&gt;

&lt;p&gt;It doesn't know that metrics.json contains evaluation metrics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use metrics: instead of outs:?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regular outputs:&lt;/p&gt;

&lt;p&gt;outs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;models/model.pkl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;are treated as artifacts (files produced by the pipeline).&lt;/p&gt;

&lt;p&gt;Metrics are different—they are values you want to compare between experiments.&lt;/p&gt;

&lt;p&gt;So we use:&lt;/p&gt;

&lt;p&gt;metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;metrics.json:
  cache: false&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tells DVC:&lt;/p&gt;

&lt;p&gt;metrics.json contains evaluation metrics.&lt;br&gt;
Keep it in Git (cache: false) instead of storing it in the DVC cache.&lt;br&gt;
Allow commands like dvc metrics show and dvc metrics diff to read it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why cache: false?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normally, DVC stores outputs in its cache.&lt;/p&gt;

&lt;p&gt;For metrics, we want the JSON file to stay in the Git repository because:&lt;/p&gt;

&lt;p&gt;it's small,&lt;br&gt;
it's easy to compare between commits,&lt;br&gt;
Git can track its history.&lt;/p&gt;

&lt;p&gt;That's why the lab requires:&lt;/p&gt;

&lt;p&gt;cache: false&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does dvc metrics show do?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running:&lt;/p&gt;

&lt;p&gt;dvc repro&lt;/p&gt;

&lt;p&gt;you can execute:&lt;/p&gt;

&lt;p&gt;dvc metrics show&lt;/p&gt;

&lt;p&gt;Instead of opening metrics.json manually, DVC displays the important values in a table, for example:&lt;/p&gt;

&lt;p&gt;Path          accuracy    f1_score&lt;br&gt;
metrics.json  1.0         1.0&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is dvc metrics diff?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you experiment with different model parameters (such as n_estimators), the metrics may change.&lt;/p&gt;

&lt;p&gt;Running:&lt;/p&gt;

&lt;p&gt;dvc metrics diff&lt;/p&gt;

&lt;p&gt;compares the metric values across Git commits, making it easy to see whether the new model performed better or worse.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-MLOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>100daysofmlops</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>Day 15: Parameterize a DVC Pipeline</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Sun, 19 Jul 2026 04:54:04 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/day-15-parameterize-a-dvc-pipeline-227k</link>
      <guid>https://dev.to/thukhakyawe_cloud/day-15-parameterize-a-dvc-pipeline-227k</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;The xFusionCorp Industries ML team manages model hyperparameters using params.yaml, enabling experiments to be conducted without altering the code. In the fraud-detection project, the train stage retrieves the n_estimators parameter from params.yaml, but this parameter is not declared to DVC, which means that changing its value does not initiate retraining. Integrate the parameter into the pipeline and illustrate the concept of parameter-driven reproducibility.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A project exists at /root/code/fraud-detection/ with a three-stage DVC pipeline (process_data, split_data, train) and a params.yaml declaring n_estimators: 100. src/models/train.py already reads n_estimators from params.yaml. Do not modify the Python files.

The train stage in dvc.yaml has no params: section, so DVC does not track n_estimators — changing it would not re-run the stage. Add a params: entry to the train stage that lists n_estimators (edit dvc.yaml, or use dvc stage add --force … -p n_estimators …).

Run the full pipeline with dvc repro.

Demonstrate parameter-driven retraining: change n_estimators to a different value (for example 200) and run dvc repro again. Only the train stage should re-execute, the new value must be recorded in dvc.lock, and models/model.pkl must be regenerated.

dvc params diff reports changes to the tracked parameter values across Git commits, which is useful when comparing experiments.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Step 1: Move into the repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/code/fraud-detection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Inspect the current pipeline&lt;/p&gt;

&lt;p&gt;Open dvc.yaml:&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="s"&gt;cat dvc.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Locate the train stage.&lt;/p&gt;

&lt;p&gt;It will look similar to:&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;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;process_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/data/process_data.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/raw/transactions.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/data/process_data.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/clean_transactions.csv&lt;/span&gt;

  &lt;span class="na"&gt;split_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/data/split_data.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/clean_transactions.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/data/split_data.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/train.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/test.csv&lt;/span&gt;

  &lt;span class="na"&gt;train&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/models/train.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/train.csv&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/models/train.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;models/model.pkl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Verify params.yaml&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="s"&gt;cat params.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;n_estimators: 100&lt;/p&gt;

&lt;p&gt;Step 4: Add the parameter to the train stage&lt;/p&gt;

&lt;p&gt;Edit dvc.yaml:&lt;/p&gt;

&lt;p&gt;vi dvc.yaml&lt;/p&gt;

&lt;p&gt;Add the highlighted section:&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;train&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/models/train.py&lt;/span&gt;

  &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/train.csv&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/models/train.py&lt;/span&gt;

  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n_estimators&lt;/span&gt;

  &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;models/model.pkl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file.&lt;/p&gt;

&lt;p&gt;Step 5: Run the pipeline&lt;/p&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;dvc repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main ➜  dvc repro
Running stage 'process_data':                                                  
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 src/data/process_data.py
&lt;span class="go"&gt;Processed 15 rows
Generating lock file 'dvc.lock'                                                
Updating lock file 'dvc.lock'

Running stage 'split_data':                                                    
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 src/data/split_data.py
&lt;span class="go"&gt;Train: 12 rows, Test: 3 rows
Updating lock file 'dvc.lock'                                                  

Running stage 'train':                                                         
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 src/models/train.py
&lt;span class="go"&gt;Trained RandomForestClassifier with n_estimators=100
Updating lock file 'dvc.lock'                                                  

To track the changes with git, run:

        git add data/processed/.gitignore dvc.lock models/.gitignore

To enable auto staging, run:

        dvc config core.autostage true
Use `dvc push` to send your updates to remote storage.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 6: Verify dvc.lock&lt;/p&gt;

&lt;p&gt;Search for the parameter:&lt;/p&gt;

&lt;p&gt;grep -A5 params dvc.lock&lt;/p&gt;

&lt;p&gt;You should see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main [!?] ➜  grep -A5 params dvc.lock
    params:
      params.yaml:
        n_estimators: 100
    outs:
    - path: models/model.pkl
      hash: md5
      md5: ba2187225d8642cbbcd4b127310ced91
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms DVC is now tracking the parameter.&lt;/p&gt;

&lt;p&gt;Step 7: Change the parameter&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vi params.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change:&lt;/p&gt;

&lt;p&gt;n_estimators: 100&lt;/p&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;p&gt;n_estimators: 200&lt;/p&gt;

&lt;p&gt;Save the file.&lt;/p&gt;

&lt;p&gt;Step 8: Run the pipeline again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main [!?] ➜  dvc repro
Stage 'process_data' didn't change, skipping                                   
Stage 'split_data' didn't change, skipping                                     
Running stage 'train':                                                         
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 src/models/train.py
&lt;span class="go"&gt;Trained RandomForestClassifier with n_estimators=200
Updating lock file 'dvc.lock'                                                  

To track the changes with git, run:

        git add dvc.lock

To enable auto staging, run:

        dvc config core.autostage true
Use `dvc push` to send your updates to remote storage.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 9: Verify dvc.lock&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-A5&lt;/span&gt; params dvc.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&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;params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;params.yaml&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;n_estimators&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;models/model.pkl&lt;/span&gt;
      &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;md5&lt;/span&gt;
      &lt;span class="na"&gt;md5&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;c74b4c9de3ba10fc6f8c3789964ec187&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 11: View parameter differences&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc params diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main [!?] ➜  dvc params diff
Path         Param         HEAD    workspace
params.yaml  n_estimators  100     200
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanation (Beginner Friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is params.yaml?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of hardcoding values like:&lt;/p&gt;

&lt;p&gt;n_estimators = 100&lt;/p&gt;

&lt;p&gt;the project stores them in a separate file:&lt;/p&gt;

&lt;p&gt;n_estimators: 100&lt;/p&gt;

&lt;p&gt;The training script reads this value automatically.&lt;/p&gt;

&lt;p&gt;This makes it easy to try different settings without changing the Python code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why isn't changing params.yaml enough?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though train.py reads params.yaml, DVC doesn't automatically know that the train stage depends on it.&lt;/p&gt;

&lt;p&gt;If the params: section is missing from dvc.yaml, DVC thinks:&lt;/p&gt;

&lt;p&gt;"Nothing important changed."&lt;/p&gt;

&lt;p&gt;So running:&lt;/p&gt;

&lt;p&gt;dvc repro&lt;/p&gt;

&lt;p&gt;may skip the training stage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does the params: section do?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding:&lt;/p&gt;

&lt;p&gt;params:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n_estimators&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;tells DVC:&lt;/p&gt;

&lt;p&gt;"The train stage depends on the value of n_estimators."&lt;/p&gt;

&lt;p&gt;Now, whenever n_estimators changes, DVC knows the model needs to be retrained.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens after changing the parameter?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Initially:&lt;/p&gt;

&lt;p&gt;n_estimators: 100&lt;/p&gt;

&lt;p&gt;After editing:&lt;/p&gt;

&lt;p&gt;n_estimators: 200&lt;/p&gt;

&lt;p&gt;When you run:&lt;/p&gt;

&lt;p&gt;dvc repro&lt;/p&gt;

&lt;p&gt;DVC compares the tracked parameter values and notices that n_estimators has changed.&lt;/p&gt;

&lt;p&gt;Since only the training configuration changed:&lt;/p&gt;

&lt;p&gt;✅ train runs again.&lt;br&gt;
✅ process_data is skipped.&lt;br&gt;
✅ split_data is skipped.&lt;/p&gt;

&lt;p&gt;This saves time by only rerunning the stage that is affected.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is dvc.lock?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After each successful run, DVC records the parameter value used.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;params:&lt;br&gt;
  params.yaml:&lt;br&gt;
    n_estimators: 200&lt;/p&gt;

&lt;p&gt;This allows anyone to reproduce the exact experiment later using the same parameter values.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does dvc params diff do?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The command:&lt;/p&gt;

&lt;p&gt;dvc params diff&lt;/p&gt;

&lt;p&gt;shows how parameter values changed between Git commits.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Path         Param          Old   New&lt;br&gt;
params.yaml  n_estimators   100   200&lt;/p&gt;

&lt;p&gt;This is useful for comparing different experiments and understanding what changed between model versions.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-MLOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>100daysofmlops</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>5.Jenkins Scheduled Jobs</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Thu, 09 Jul 2026 11:30:00 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/5jenkins-scheduled-jobs-1n0a</link>
      <guid>https://dev.to/thukhakyawe_cloud/5jenkins-scheduled-jobs-1n0a</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;The devops team of xFusionCorp Industries is working on to setup centralised logging management system to maintain and analyse server logs easily. Since it will take some time to implement, they wanted to gather some server logs on a regular basis. At least one of the app servers is having issues with the Apache server. The team needs Apache logs so that they can identify and troubleshoot the issues easily if they arise. So they decided to create a Jenkins job to collect logs from the server. Please create/configure a Jenkins job as per details mentioned below:&lt;/p&gt;

&lt;p&gt;Click on the Jenkins button on the top bar to access the Jenkins UI. Login using username admin and password Adm!n321&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a Jenkins jobs named copy-logs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure it to periodically build every 5 minutes to copy the Apache logs (both access_log and error_log) from App Server 1 (stapp01) from the default logs location to location /usr/src/itadmin on the Storage Server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build the job at least once so that the logs are copied and can be verified.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You might need to install some plugins and restart Jenkins. We recommend selecting Restart Jenkins when installation is complete and no jobs are running in the update centre. Refresh the page if the UI gets stuck after a restart.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define the cron expression as required (e.g. */10 * * * * to run every 10 minutes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For scenarios that require web UI changes, take screenshots or record your work (e.g. using loom.com) so you can share it for review if the task is marked incomplete.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Add SSH Keys &lt;/p&gt;

&lt;p&gt;Step 1: Open the Lab Terminal&lt;/p&gt;

&lt;p&gt;This cannot be done from the Jenkins UI.&lt;/p&gt;

&lt;p&gt;Open the Terminal provided by the KodeKloud lab (usually connected to the jump-host).&lt;/p&gt;

&lt;p&gt;Step 2: SSH to the Jenkins Server&lt;/p&gt;

&lt;p&gt;ssh jenkins@jenkins&lt;/p&gt;

&lt;p&gt;Password:&lt;/p&gt;

&lt;p&gt;j@rv!s&lt;/p&gt;

&lt;p&gt;Step 3: Generate an SSH Key (if one doesn't exist)&lt;/p&gt;

&lt;p&gt;Check first:&lt;/p&gt;

&lt;p&gt;ls -la ~/.ssh&lt;/p&gt;

&lt;p&gt;If you don't see id_rsa and id_rsa.pub, run:&lt;/p&gt;

&lt;p&gt;ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa&lt;/p&gt;

&lt;p&gt;Step 4: Trust and Copy the Key to stapp01&lt;/p&gt;

&lt;p&gt;ssh-copy-id tony@stapp01&lt;/p&gt;

&lt;p&gt;Password:&lt;/p&gt;

&lt;p&gt;Ir0nM@n&lt;/p&gt;

&lt;p&gt;When prompted:&lt;/p&gt;

&lt;p&gt;Are you sure you want to continue connecting (yes/no)?&lt;/p&gt;

&lt;p&gt;Type:&lt;/p&gt;

&lt;p&gt;yes&lt;/p&gt;

&lt;p&gt;Step 5: Verify&lt;/p&gt;

&lt;p&gt;ssh tony@stapp01 hostname&lt;/p&gt;

&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;stapp01&lt;/p&gt;

&lt;p&gt;without asking for a password.&lt;/p&gt;

&lt;p&gt;Step 6: Copy the Key to the Storage Server&lt;/p&gt;

&lt;p&gt;From the Jenkins server:&lt;/p&gt;

&lt;p&gt;ssh-copy-id natasha@ststor01&lt;/p&gt;

&lt;p&gt;Password:&lt;/p&gt;

&lt;p&gt;Bl@kW&lt;/p&gt;

&lt;p&gt;Again, answer yes if asked about the host key.&lt;/p&gt;

&lt;p&gt;Step 7: Verify&lt;/p&gt;

&lt;p&gt;ssh natasha@ststor01 hostname&lt;/p&gt;

&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;ststor01&lt;/p&gt;




&lt;p&gt;Step 1: Log in to Jenkins&lt;br&gt;
Click the Jenkins button.&lt;br&gt;
Login using:&lt;/p&gt;

&lt;p&gt;Username:&lt;/p&gt;

&lt;p&gt;admin&lt;/p&gt;

&lt;p&gt;Password:&lt;/p&gt;

&lt;p&gt;Adm!n321&lt;/p&gt;

&lt;p&gt;Step 2: Create the Jenkins Job&lt;br&gt;
Click New Item&lt;br&gt;
Enter:&lt;br&gt;
copy-logs&lt;br&gt;
Select:&lt;br&gt;
Freestyle project&lt;br&gt;
Click OK&lt;/p&gt;

&lt;p&gt;Step 3: Configure Build Trigger&lt;/p&gt;

&lt;p&gt;Scroll to Build Triggers&lt;/p&gt;

&lt;p&gt;Enable:&lt;/p&gt;

&lt;p&gt;✔ Build periodically&lt;/p&gt;

&lt;p&gt;Enter exactly:&lt;/p&gt;

&lt;p&gt;*/5 * * * *&lt;/p&gt;

&lt;p&gt;⚠️ Do not use:&lt;/p&gt;

&lt;p&gt;H/5 * * * *&lt;/p&gt;

&lt;p&gt;The validator checks the exact cron expression.&lt;/p&gt;

&lt;p&gt;Step 4: Configure Build Step&lt;/p&gt;

&lt;p&gt;Scroll to:&lt;/p&gt;

&lt;p&gt;Build&lt;/p&gt;

&lt;p&gt;Click:&lt;/p&gt;

&lt;p&gt;Add build step&lt;br&gt;
→ Execute shell&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /tmp/apache-logs

scp &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no &lt;span class="se"&gt;\&lt;/span&gt;
tony@stapp01:/var/log/httpd/access_log &lt;span class="se"&gt;\&lt;/span&gt;
/tmp/apache-logs/

scp &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no &lt;span class="se"&gt;\&lt;/span&gt;
tony@stapp01:/var/log/httpd/error_log &lt;span class="se"&gt;\&lt;/span&gt;
/tmp/apache-logs/

scp &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no &lt;span class="se"&gt;\&lt;/span&gt;
/tmp/apache-logs/&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
natasha@ststor01:/usr/src/itadmin/

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /tmp/apache-logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your app server uses /var/log/apache2/, replace /var/log/httpd/ with /var/log/apache2/ in the script.&lt;/p&gt;

&lt;p&gt;Click Save&lt;/p&gt;

&lt;p&gt;Step 5: Build the Job&lt;/p&gt;

&lt;p&gt;Open:&lt;/p&gt;

&lt;p&gt;copy-logs&lt;/p&gt;

&lt;p&gt;Click:&lt;/p&gt;

&lt;p&gt;Build Now&lt;/p&gt;

&lt;p&gt;Wait for the build to complete.&lt;/p&gt;

&lt;p&gt;Step 6: Verify Successful Build&lt;/p&gt;

&lt;p&gt;Open:&lt;/p&gt;

&lt;p&gt;Build History&lt;br&gt;
→ Latest Build&lt;br&gt;
→ Console Output&lt;/p&gt;

&lt;p&gt;Verify the last line shows:&lt;/p&gt;

&lt;p&gt;Finished: SUCCESS&lt;/p&gt;

&lt;p&gt;There should be no SCP or SSH errors.&lt;/p&gt;

&lt;p&gt;Step 7: Validate the Lab&lt;/p&gt;

&lt;p&gt;Before clicking Validate, verify:&lt;/p&gt;

&lt;p&gt;Job name is correct.&lt;br&gt;
Cron schedule is correct.&lt;br&gt;
Build completed successfully.&lt;br&gt;
Both Apache log files were copied to:&lt;br&gt;
/usr/src/itadmin&lt;/p&gt;

&lt;p&gt;on ststor01.&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanations (Beginner Friendly)&lt;/p&gt;

&lt;p&gt;What are we trying to accomplish?&lt;/p&gt;

&lt;p&gt;Apache generates log files whenever users access the website or when errors occur.&lt;/p&gt;

&lt;p&gt;Instead of manually logging into the server to collect logs, Jenkins will automatically copy them to the storage server every 5 minutes.&lt;/p&gt;

&lt;p&gt;Step 1: Create a Temporary Folder&lt;br&gt;
mkdir -p /tmp/apache-logs&lt;br&gt;
What does it do?&lt;/p&gt;

&lt;p&gt;Creates a temporary directory on the Jenkins server.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;/tmp/apache-logs&lt;/p&gt;

&lt;p&gt;This folder temporarily stores the log files before sending them to the storage server.&lt;/p&gt;

&lt;p&gt;Step 2: Copy the Apache Access Log&lt;br&gt;
scp -o StrictHostKeyChecking=no \&lt;br&gt;
tony@stapp01:/var/log/httpd/access_log \&lt;br&gt;
/tmp/apache-logs/&lt;br&gt;
What is access_log?&lt;/p&gt;

&lt;p&gt;The Apache access log records every request made to the web server.&lt;/p&gt;

&lt;p&gt;Example entries include:&lt;/p&gt;

&lt;p&gt;Client IP address&lt;br&gt;
Date and time&lt;br&gt;
Requested URL&lt;br&gt;
HTTP status code (200, 404, 500, etc.)&lt;/p&gt;

&lt;p&gt;This helps administrators analyze website traffic and user requests.&lt;/p&gt;

&lt;p&gt;Step 3: Copy the Apache Error Log&lt;br&gt;
scp -o StrictHostKeyChecking=no \&lt;br&gt;
tony@stapp01:/var/log/httpd/error_log \&lt;br&gt;
/tmp/apache-logs/&lt;br&gt;
What is error_log?&lt;/p&gt;

&lt;p&gt;The Apache error log records problems such as:&lt;/p&gt;

&lt;p&gt;Website errors&lt;br&gt;
PHP errors&lt;br&gt;
Missing files&lt;br&gt;
Apache startup failures&lt;/p&gt;

&lt;p&gt;These logs are essential for troubleshooting.&lt;/p&gt;

&lt;p&gt;Step 4: Copy Logs to the Storage Server&lt;br&gt;
scp -o StrictHostKeyChecking=no \&lt;br&gt;
/tmp/apache-logs/* \&lt;br&gt;
natasha@ststor01:/usr/src/itadmin/&lt;br&gt;
What does this do?&lt;/p&gt;

&lt;p&gt;It transfers both log files from the Jenkins server to the Storage Server.&lt;/p&gt;

&lt;p&gt;Destination:&lt;/p&gt;

&lt;p&gt;/usr/src/itadmin&lt;/p&gt;

&lt;p&gt;Using a storage server keeps logs centralized and prevents them from being lost if the application server has issues.&lt;/p&gt;

&lt;p&gt;Step 5: Remove Temporary Files&lt;br&gt;
rm -rf /tmp/apache-logs&lt;br&gt;
Why?&lt;/p&gt;

&lt;p&gt;Once the logs have been copied successfully, the temporary folder is no longer needed.&lt;/p&gt;

&lt;p&gt;Deleting it:&lt;/p&gt;

&lt;p&gt;Frees disk space.&lt;br&gt;
Keeps the Jenkins server clean.&lt;br&gt;
Step 6: Automatic Scheduling&lt;/p&gt;

&lt;p&gt;The cron expression:&lt;/p&gt;

&lt;p&gt;*/5 * * * *&lt;/p&gt;

&lt;p&gt;means:&lt;/p&gt;

&lt;p&gt;Field   Meaning&lt;br&gt;
*/5 Every 5 minutes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Every hour&lt;/li&gt;
&lt;li&gt;  Every day&lt;/li&gt;
&lt;li&gt;  Every month&lt;/li&gt;
&lt;li&gt;  Every weekday&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jenkins automatically runs the job every 5 minutes.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-DevOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>jenkins</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>4.Jenkins Database Backup Job</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Thu, 09 Jul 2026 08:30:00 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/4jenkins-database-backup-job-2kng</link>
      <guid>https://dev.to/thukhakyawe_cloud/4jenkins-database-backup-job-2kng</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;There is a requirement to create a Jenkins job to automate the database backup. Below you can find more details to accomplish this task:&lt;/p&gt;

&lt;p&gt;Click on the Jenkins button on the top bar to access the Jenkins UI. Login using username admin and password Adm!n321.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a Jenkins job named database-backup.

Configure it to take a database dump of the kodekloud_db01 database present on the App server (stapp01) in Stratos Datacenter, the database user is kodekloud_roy and password is asdfgdsd.

The dump should be named in db_$(date +%F).sql format, where date +%F is the current date.

Copy the db_$(date +%F).sql dump to the Storage server (ststor01) under location /home/natasha/db_backups.

Further, schedule this job to run periodically at */10 * * * * (please use this exact schedule format).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You might need to install some plugins and restart Jenkins service. So, we recommend clicking on Restart Jenkins when installation is complete and no jobs are running on plugin installation/update page i.e update centre. Also, Jenkins UI sometimes gets stuck when Jenkins service restarts in the back end. In this case please make sure to refresh the UI page.

Please make sure to define you cron expression like this */10 * * * * (this is just an example to run job every 10 minutes).

For these kind of scenarios requiring changes to be done in a web UI, please take screenshots so that you can share it with us for review in case your task is marked incomplete. You may also consider using a screen recording software such as loom.com to record and share your work.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Add SSH Keys &lt;/p&gt;

&lt;p&gt;Step 1: Open the Lab Terminal&lt;/p&gt;

&lt;p&gt;This cannot be done from the Jenkins UI.&lt;/p&gt;

&lt;p&gt;Open the Terminal provided by the KodeKloud lab (usually connected to the jump-host).&lt;/p&gt;

&lt;p&gt;Step 2: SSH to the Jenkins Server&lt;/p&gt;

&lt;p&gt;ssh jenkins@jenkins&lt;/p&gt;

&lt;p&gt;Password:&lt;/p&gt;

&lt;p&gt;j@rv!s&lt;/p&gt;

&lt;p&gt;Step 3: Generate an SSH Key (if one doesn't exist)&lt;/p&gt;

&lt;p&gt;Check first:&lt;/p&gt;

&lt;p&gt;ls -la ~/.ssh&lt;/p&gt;

&lt;p&gt;If you don't see id_rsa and id_rsa.pub, run:&lt;/p&gt;

&lt;p&gt;ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa&lt;/p&gt;

&lt;p&gt;Step 4: Trust and Copy the Key to stapp01&lt;/p&gt;

&lt;p&gt;ssh-copy-id tony@stapp01&lt;/p&gt;

&lt;p&gt;Password:&lt;/p&gt;

&lt;p&gt;Ir0nM@n&lt;/p&gt;

&lt;p&gt;When prompted:&lt;/p&gt;

&lt;p&gt;Are you sure you want to continue connecting (yes/no)?&lt;/p&gt;

&lt;p&gt;Type:&lt;/p&gt;

&lt;p&gt;yes&lt;/p&gt;

&lt;p&gt;Step 5: Verify&lt;/p&gt;

&lt;p&gt;ssh tony@stapp01 hostname&lt;/p&gt;

&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;stapp01&lt;/p&gt;

&lt;p&gt;without asking for a password.&lt;/p&gt;

&lt;p&gt;Step 6: Copy the Key to the Storage Server&lt;/p&gt;

&lt;p&gt;From the Jenkins server:&lt;/p&gt;

&lt;p&gt;ssh-copy-id natasha@ststor01&lt;/p&gt;

&lt;p&gt;Password:&lt;/p&gt;

&lt;p&gt;Bl@kW&lt;/p&gt;

&lt;p&gt;Again, answer yes if asked about the host key.&lt;/p&gt;

&lt;p&gt;Step 7: Verify&lt;/p&gt;

&lt;p&gt;ssh natasha@ststor01 hostname&lt;/p&gt;

&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;ststor01&lt;/p&gt;




&lt;p&gt;Step 1: Log in to Jenkins&lt;br&gt;
Click the Jenkins button.&lt;br&gt;
Login using:&lt;br&gt;
Username: admin&lt;br&gt;
Password: Adm!n321&lt;/p&gt;

&lt;p&gt;Step 2: Create the Jenkins Job&lt;br&gt;
Click New Item.&lt;br&gt;
Enter:&lt;br&gt;
database-backup&lt;br&gt;
Select:&lt;br&gt;
Freestyle project&lt;br&gt;
Click OK.&lt;/p&gt;

&lt;p&gt;Step 3: Configure the Build Trigger&lt;/p&gt;

&lt;p&gt;Scroll to Build Triggers.&lt;/p&gt;

&lt;p&gt;Enable:&lt;/p&gt;

&lt;p&gt;✔ Build periodically&lt;/p&gt;

&lt;p&gt;Enter exactly:&lt;/p&gt;

&lt;p&gt;*/10 * * * *&lt;/p&gt;

&lt;p&gt;⚠️ Do not use&lt;/p&gt;

&lt;p&gt;H/10 * * * *&lt;/p&gt;

&lt;p&gt;The validator checks for the exact cron expression.&lt;/p&gt;

&lt;p&gt;Step 4: Configure the Build Step&lt;/p&gt;

&lt;p&gt;Scroll to Build.&lt;/p&gt;

&lt;p&gt;Click:&lt;/p&gt;

&lt;p&gt;Add build step&lt;br&gt;
→ Execute shell&lt;/p&gt;

&lt;p&gt;Paste the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /tmp/db-backup

ssh tony@stapp01 &lt;span class="s2"&gt;"mysqldump -u kodekloud_roy -p'asdfgdsd' kodekloud_db01"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/db-backup/db_&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F&lt;span class="si"&gt;)&lt;/span&gt;.sql

scp &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no &lt;span class="se"&gt;\&lt;/span&gt;
/tmp/db-backup/&lt;span class="k"&gt;*&lt;/span&gt;.sql &lt;span class="se"&gt;\&lt;/span&gt;
natasha@ststor01:/home/natasha/db_backups/

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /tmp/db-backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click Save.&lt;/p&gt;

&lt;p&gt;Step 5: Build the Job&lt;/p&gt;

&lt;p&gt;Open:&lt;/p&gt;

&lt;p&gt;database-backup&lt;/p&gt;

&lt;p&gt;Click:&lt;/p&gt;

&lt;p&gt;Build Now&lt;/p&gt;

&lt;p&gt;Wait until the build finishes.&lt;/p&gt;

&lt;p&gt;Step 6: Verify the Build&lt;/p&gt;

&lt;p&gt;Open:&lt;/p&gt;

&lt;p&gt;Build History&lt;br&gt;
→ Latest Build&lt;br&gt;
→ Console Output&lt;/p&gt;

&lt;p&gt;The last line should show:&lt;/p&gt;

&lt;p&gt;Finished: SUCCESS&lt;/p&gt;

&lt;p&gt;There should be no errors related to:&lt;/p&gt;

&lt;p&gt;SSH&lt;br&gt;
mysqldump&lt;br&gt;
SCP&lt;/p&gt;

&lt;p&gt;Step 7: Validate the Lab&lt;/p&gt;

&lt;p&gt;Before clicking Validate, verify:&lt;/p&gt;

&lt;p&gt;Job name is correct.&lt;br&gt;
Cron schedule is correct.&lt;br&gt;
Build completed successfully.&lt;br&gt;
SQL file was copied to:&lt;br&gt;
/home/natasha/db_backups&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanations (Beginner Friendly)&lt;/p&gt;

&lt;p&gt;What are we trying to accomplish?&lt;/p&gt;

&lt;p&gt;Instead of manually backing up the database every time, Jenkins will automate the entire backup process.&lt;/p&gt;

&lt;p&gt;Every time the job runs, Jenkins will:&lt;/p&gt;

&lt;p&gt;Connect to the application server.&lt;br&gt;
Export the database.&lt;br&gt;
Save it as a SQL file.&lt;br&gt;
Copy it to the storage server.&lt;br&gt;
Remove temporary files.&lt;br&gt;
Step 1: Create a Temporary Folder&lt;br&gt;
mkdir -p /tmp/db-backup&lt;br&gt;
What does it do?&lt;/p&gt;

&lt;p&gt;Creates a temporary folder on the Jenkins server.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;/tmp/db-backup&lt;br&gt;
Why?&lt;/p&gt;

&lt;p&gt;We need a temporary location to store the SQL backup before sending it to the storage server.&lt;/p&gt;

&lt;p&gt;The option:&lt;/p&gt;

&lt;p&gt;-p&lt;/p&gt;

&lt;p&gt;means:&lt;/p&gt;

&lt;p&gt;Create the directory only if it doesn't already exist.&lt;/p&gt;

&lt;p&gt;Step 2: Create the Database Backup&lt;br&gt;
ssh tony@stapp01 "mysqldump -u kodekloud_roy -p'asdfgdsd' kodekloud_db01" \&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;/tmp/db-backup/db_$(date +%F).sql&lt;br&gt;
What happens?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jenkins connects to:&lt;/p&gt;

&lt;p&gt;stapp01&lt;/p&gt;

&lt;p&gt;and runs:&lt;/p&gt;

&lt;p&gt;mysqldump&lt;/p&gt;

&lt;p&gt;This exports the entire database.&lt;/p&gt;

&lt;p&gt;The output is redirected to a file on the Jenkins server:&lt;/p&gt;

&lt;p&gt;db_YYYY-MM-DD.sql&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;db_2026-07-06.sql&lt;br&gt;
Understanding the mysqldump command&lt;br&gt;
mysqldump&lt;/p&gt;

&lt;p&gt;Creates a backup of a MySQL database.&lt;/p&gt;

&lt;p&gt;-u&lt;/p&gt;

&lt;p&gt;Specifies the database username.&lt;/p&gt;

&lt;p&gt;-p'asdfgdsd'&lt;/p&gt;

&lt;p&gt;Specifies the database password.&lt;/p&gt;

&lt;p&gt;kodekloud_db01&lt;/p&gt;

&lt;p&gt;Is the database name to back up.&lt;/p&gt;

&lt;p&gt;Step 3: Copy the Backup&lt;br&gt;
scp -o StrictHostKeyChecking=no \&lt;br&gt;
/tmp/db-backup/*.sql \&lt;br&gt;
natasha@ststor01:/home/natasha/db_backups/&lt;br&gt;
What happens?&lt;/p&gt;

&lt;p&gt;The backup file is copied from the Jenkins server to:&lt;/p&gt;

&lt;p&gt;ststor01&lt;/p&gt;

&lt;p&gt;Destination folder:&lt;/p&gt;

&lt;p&gt;/home/natasha/db_backups&lt;br&gt;
What does scp mean?&lt;br&gt;
scp&lt;/p&gt;

&lt;p&gt;stands for:&lt;/p&gt;

&lt;p&gt;Secure Copy&lt;/p&gt;

&lt;p&gt;It copies files securely over SSH.&lt;/p&gt;

&lt;p&gt;What does this option do?&lt;br&gt;
-o StrictHostKeyChecking=no&lt;/p&gt;

&lt;p&gt;It prevents SSH from asking:&lt;/p&gt;

&lt;p&gt;Do you trust this server?&lt;/p&gt;

&lt;p&gt;Since Jenkins jobs run automatically, they cannot answer interactive questions.&lt;/p&gt;

&lt;p&gt;Step 4: Delete Temporary Files&lt;br&gt;
rm -rf /tmp/db-backup&lt;br&gt;
Why?&lt;/p&gt;

&lt;p&gt;The SQL backup has already been copied to the storage server.&lt;/p&gt;

&lt;p&gt;Removing the temporary folder:&lt;/p&gt;

&lt;p&gt;Saves disk space.&lt;br&gt;
Keeps the Jenkins server clean.&lt;br&gt;
Step 5: Automatic Scheduling&lt;/p&gt;

&lt;p&gt;The cron expression:&lt;/p&gt;

&lt;p&gt;*/10 * * * *&lt;/p&gt;

&lt;p&gt;means:&lt;/p&gt;

&lt;p&gt;Field   Meaning&lt;br&gt;
*/10    Every 10 minutes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Every hour&lt;/li&gt;
&lt;li&gt;  Every day&lt;/li&gt;
&lt;li&gt;  Every month&lt;/li&gt;
&lt;li&gt;  Every weekday&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So Jenkins automatically performs the backup every 10 minutes.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-DevOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>jenkins</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>3.Jenkins Workspaces</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Thu, 09 Jul 2026 05:30:00 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/3jenkins-workspaces-2bb6</link>
      <guid>https://dev.to/thukhakyawe_cloud/3jenkins-workspaces-2bb6</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;Some developers are working on a common repository where they are testing some features for an application. They are having three branches (excluding the master branch) in this repository where they are adding changes related to these different features. They want to test these changes on Stratos DC app servers so they need a Jenkins job using which they can deploy these different branches as per requirements. Configure a Jenkins job accordingly.&lt;/p&gt;

&lt;p&gt;Click on the Jenkins button on the top bar to access the Jenkins UI. Login using username admin and password Adm!n321.&lt;/p&gt;

&lt;p&gt;Similarly, click on Gitea button to access the Gitea page. Login to Gitea server using username sarah and password Sarah_pass123.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;There is a Git repository named web_app on Gitea where developers are pushing their changes. It has three branches version1, version2 and version3 (excluding the master branch). You need not to make any changes in the repository.

Create a Jenkins job named app-job.

Configure this job to have a choice parameter named Branch with choices as given below:

version1

version2

version3

Configure the job to fetch changes from above mentioned Git repository and make sure it should fetches the changes from the respective branch which you are passing as a choice in the choice parameter while building the job. For example if you choose version1 then it must fetch and deploy the changes from branch version1.

Configure this job to use custom workspace rather than a default workspace and custom workspace directory should be created under /var/lib/jenkins (for example /var/lib/jenkins/version1) location rather than under any sub-directory etc. The job should use a workspace as per the value you will pass for Branch parameter while building the job. For example if you choose version1 while building the job then it should create a workspace directory called version1 and should fetch Git repository etc within that directory only.

Configure the job to deploy code (fetched from Git repository) on App Server 1 (stapp01) under /var/www/html directory.

You can access the website by clicking on App button.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You might need to install some plugins and restart Jenkins service. So, we recommend clicking on Restart Jenkins when installation is complete and no jobs are running on plugin installation/update page i.e update centre. Also, Jenkins UI sometimes gets stuck when Jenkins service restarts in the back end. In this case please make sure to refresh the UI page.

For these kind of scenarios requiring changes to be done in a web UI, please take screenshots so that you can share it with us for review in case your task is marked incomplete. You may also consider using a screen recording software such as loom.com to record and share your work.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Install these plugins&lt;/p&gt;

&lt;p&gt;Git&lt;br&gt;
Publish Over SSH&lt;/p&gt;

&lt;p&gt;Jenkins&lt;br&gt;
Username: admin&lt;br&gt;
Password: Adm!n321&lt;/p&gt;

&lt;p&gt;Gitea&lt;br&gt;
Username: sarah&lt;br&gt;
Password: Sarah_pass123&lt;/p&gt;

&lt;p&gt;Open the web_app repository.&lt;/p&gt;

&lt;p&gt;Step 2: Create the Jenkins Job&lt;/p&gt;

&lt;p&gt;New Item&lt;br&gt;
Name:&lt;br&gt;
app-job&lt;br&gt;
Select Freestyle project&lt;br&gt;
Click OK&lt;/p&gt;

&lt;p&gt;Step 3: Add the Choice Parameter&lt;/p&gt;

&lt;p&gt;Enable:&lt;/p&gt;

&lt;p&gt;This project is parameterized&lt;/p&gt;

&lt;p&gt;Add Choice Parameter.&lt;/p&gt;

&lt;p&gt;Name:&lt;/p&gt;

&lt;p&gt;Branch&lt;/p&gt;

&lt;p&gt;Choices (one per line):&lt;/p&gt;

&lt;p&gt;version1&lt;br&gt;
version2&lt;br&gt;
version3&lt;/p&gt;

&lt;p&gt;Step 4: Configure the Custom Workspace&lt;/p&gt;

&lt;p&gt;Under Advanced Project Options, enable:&lt;/p&gt;

&lt;p&gt;Use custom workspace&lt;/p&gt;

&lt;p&gt;Directory:&lt;/p&gt;

&lt;p&gt;/var/lib/jenkins/${Branch}&lt;/p&gt;

&lt;p&gt;⚠️ Do not use:&lt;/p&gt;

&lt;p&gt;/var/lib/jenkins/workspace/${Branch}&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;/var/lib/jenkins/version1&lt;/p&gt;

&lt;p&gt;The workspace must be dynamic.&lt;/p&gt;

&lt;p&gt;Step 5: Configure Git&lt;/p&gt;

&lt;p&gt;Source Code Management&lt;/p&gt;

&lt;p&gt;Select:&lt;/p&gt;

&lt;p&gt;Git&lt;/p&gt;

&lt;p&gt;Repository URL&lt;/p&gt;

&lt;p&gt;Use the HTTPS clone URL from Gitea.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://3000-port-ml3qg35wxs4bogvv.labs.kodekloud.com/sarah/web_app.git" rel="noopener noreferrer"&gt;https://3000-port-ml3qg35wxs4bogvv.labs.kodekloud.com/sarah/web_app.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Credentials&lt;/p&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;p&gt;sarah&lt;br&gt;
Sarah_pass123&lt;br&gt;
Branches to build&lt;/p&gt;

&lt;p&gt;Use exactly:&lt;/p&gt;

&lt;p&gt;*/${Branch}&lt;/p&gt;

&lt;p&gt;⚠️ Do not use:&lt;/p&gt;

&lt;p&gt;*/version1&lt;br&gt;
master&lt;br&gt;
origin/version1&lt;/p&gt;

&lt;p&gt;Step 6: Deploy to stapp01&lt;/p&gt;

&lt;p&gt;This is where most people fail.&lt;/p&gt;

&lt;p&gt;The task requires:&lt;/p&gt;

&lt;p&gt;Deploy code on App Server 1 (stapp01)&lt;/p&gt;

&lt;p&gt;If Publish Over SSH is available (as in your previous lab), configure it.&lt;/p&gt;

&lt;p&gt;Global Configuration&lt;/p&gt;

&lt;p&gt;Go to:&lt;/p&gt;

&lt;p&gt;Manage Jenkins&lt;br&gt;
→ System&lt;br&gt;
→ Publish over SSH&lt;/p&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;p&gt;Field   Value&lt;br&gt;
Name    stapp01&lt;br&gt;
Hostname    stapp01&lt;br&gt;
Username    tony&lt;br&gt;
Password    Ir0nM@n&lt;br&gt;
Remote Directory    /var/www/html&lt;/p&gt;

&lt;p&gt;Test Configuration → Success&lt;/p&gt;

&lt;p&gt;Save.&lt;/p&gt;

&lt;p&gt;Post-build Action&lt;/p&gt;

&lt;p&gt;Add:&lt;/p&gt;

&lt;p&gt;Send build artifacts over SSH&lt;/p&gt;

&lt;p&gt;Server:&lt;/p&gt;

&lt;p&gt;stapp01&lt;/p&gt;

&lt;p&gt;Transfer Set:&lt;/p&gt;

&lt;p&gt;Source files&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;p&gt;⚠️ Use ** instead of index.html to ensure all checked-out files are transferred.&lt;/p&gt;

&lt;p&gt;Remote Directory:&lt;/p&gt;

&lt;p&gt;Leave blank if already configured globally, or set:&lt;/p&gt;

&lt;p&gt;/var/www/html&lt;/p&gt;

&lt;p&gt;Step 7: Build&lt;/p&gt;

&lt;p&gt;Click:&lt;/p&gt;

&lt;p&gt;Build with Parameters&lt;/p&gt;

&lt;p&gt;Choose:&lt;/p&gt;

&lt;p&gt;Branch = version1&lt;/p&gt;

&lt;p&gt;Run.&lt;/p&gt;

&lt;p&gt;After success:&lt;/p&gt;

&lt;p&gt;Open App&lt;br&gt;
Verify it displays the version1 content.&lt;/p&gt;

&lt;p&gt;Step 8: Verify Dynamic Branch Selection&lt;/p&gt;

&lt;p&gt;Repeat with:&lt;/p&gt;

&lt;p&gt;Branch = version2&lt;/p&gt;

&lt;p&gt;Refresh the App page.&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;Branch = version3&lt;/p&gt;

&lt;p&gt;Refresh again.&lt;/p&gt;

&lt;p&gt;The page content should change according to the selected branch.&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanations (Beginner Friendly)&lt;/p&gt;

&lt;p&gt;Why use a Choice Parameter?&lt;/p&gt;

&lt;p&gt;Instead of creating three separate jobs, you create one job that can deploy different branches based on the selected parameter.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use ${Branch}?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you choose:&lt;/p&gt;

&lt;p&gt;version2&lt;/p&gt;

&lt;p&gt;Jenkins automatically replaces:&lt;/p&gt;

&lt;p&gt;${Branch}&lt;/p&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;p&gt;version2&lt;/p&gt;

&lt;p&gt;This affects:&lt;/p&gt;

&lt;p&gt;the Git branch to clone&lt;br&gt;
the workspace directory&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use /var/lib/jenkins/${Branch}?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each branch gets its own workspace:&lt;/p&gt;

&lt;p&gt;version1&lt;br&gt;
→ /var/lib/jenkins/version1&lt;/p&gt;

&lt;p&gt;version2&lt;br&gt;
→ /var/lib/jenkins/version2&lt;/p&gt;

&lt;p&gt;version3&lt;br&gt;
→ /var/lib/jenkins/version3&lt;/p&gt;

&lt;p&gt;This prevents branches from overwriting each other's files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use */${Branch}?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tells Git:&lt;/p&gt;

&lt;p&gt;Clone whichever branch the user selected.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;p&gt;Branch = version1&lt;br&gt;
→ */version1&lt;/p&gt;

&lt;p&gt;Branch = version2&lt;br&gt;
→ */version2&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use ** for Source files?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Publish Over SSH plugin transfers files matching the pattern.&lt;/p&gt;

&lt;p&gt;Using:&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;p&gt;copies the entire checked-out workspace.&lt;/p&gt;

&lt;p&gt;Using only:&lt;/p&gt;

&lt;p&gt;index.html&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-DevOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>jenkins</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>2.Jenkins Parameterized Builds</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Thu, 09 Jul 2026 02:30:00 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/2jenkins-parameterized-builds-422g</link>
      <guid>https://dev.to/thukhakyawe_cloud/2jenkins-parameterized-builds-422g</guid>
      <description>&lt;h1&gt;
  
  
  Lab Informaiton
&lt;/h1&gt;

&lt;p&gt;A new DevOps Engineer has joined the team and he will be assigned some Jenkins related tasks. Before that, the team wanted to test a simple parameterized job to understand basic functionality of parameterized builds. He is given a simple parameterized job to build in Jenkins. Please find more details below:&lt;/p&gt;

&lt;p&gt;Click on the Jenkins button on the top bar to access the Jenkins UI. Login using username admin and password Adm!n321.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a parameterized job which should be named as parameterized-job&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a string parameter named Stage; its default value should be Build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a choice parameter named env; its choices should be Development, Staging and Production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure job to execute a shell command, which should echo both parameter values (you are passing in the job).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build the Jenkins job at least once with choice parameter value Staging to make sure it passes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You might need to install some plugins and restart Jenkins service. So, we recommend clicking on Restart Jenkins when installation is complete and no jobs are running on plugin installation/update page i.e update centre. Also, Jenkins UI sometimes gets stuck when Jenkins service restarts in the back end. In this case, please make sure to refresh the UI page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For these kind of scenarios requiring changes to be done in a web UI, please take screenshots so that you can share it with us for review in case your task is marked incomplete. You may also consider using a screen recording software such as loom.com to record and share your work.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Step 1: Log in to Jenkins&lt;br&gt;
Click the Jenkins button on the top bar.&lt;br&gt;
Login with:&lt;br&gt;
Username: admin&lt;br&gt;
Password: Adm!n321&lt;/p&gt;

&lt;p&gt;Step 2: Create the Job&lt;br&gt;
From the Jenkins Dashboard, click New Item.&lt;br&gt;
Enter the job name: parameterized-job&lt;br&gt;
Select Freestyle project.&lt;br&gt;
Click OK.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkysgqtsn73rea4esg3fk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkysgqtsn73rea4esg3fk.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 3: Enable Parameterized Build&lt;br&gt;
In the job configuration page, scroll to This project is parameterized.&lt;br&gt;
Check the box:&lt;br&gt;
This project is parameterized&lt;/p&gt;

&lt;p&gt;Step 4: Add String Parameter&lt;br&gt;
Click Add Parameter.&lt;br&gt;
Select String Parameter.&lt;br&gt;
Configure:&lt;br&gt;
Field           Value&lt;br&gt;
Name            Stage&lt;br&gt;
Default Value   Build&lt;/p&gt;

&lt;p&gt;It should look like:&lt;/p&gt;

&lt;p&gt;Name: Stage&lt;br&gt;
Default Value: Build&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2u7yv8hks0n36rpkevhq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2u7yv8hks0n36rpkevhq.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 5: Add Choice Parameter&lt;br&gt;
Click Add Parameter again.&lt;br&gt;
Select Choice Parameter.&lt;br&gt;
Configure:&lt;br&gt;
Field           Value&lt;br&gt;
Name            env&lt;/p&gt;

&lt;p&gt;Choices (one per line):&lt;/p&gt;

&lt;p&gt;Development&lt;br&gt;
Staging&lt;br&gt;
Production&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzqih6e37wjk0tss47nam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzqih6e37wjk0tss47nam.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 6: Configure Build Step&lt;br&gt;
Scroll to the Build section.&lt;br&gt;
Click Add build step → Execute shell.&lt;br&gt;
Enter:&lt;br&gt;
echo "Stage: $Stage"&lt;br&gt;
echo "Environment: $env"&lt;br&gt;
Click Save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F19rwayj1mgkuo2l6lae8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F19rwayj1mgkuo2l6lae8.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 7: Build the Job&lt;br&gt;
Open parameterized-job.&lt;br&gt;
Click:&lt;br&gt;
Build with Parameters&lt;/p&gt;

&lt;p&gt;(not "Build Now")&lt;/p&gt;

&lt;p&gt;Set:&lt;br&gt;
Parameter   Value&lt;br&gt;
Stage       Build&lt;br&gt;
env         Staging&lt;br&gt;
Click Build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnw6sv0cly106e2143sm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnw6sv0cly106e2143sm8.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 8: Verify Successful Build&lt;br&gt;
Open the latest build.&lt;br&gt;
Click Console Output.&lt;br&gt;
Confirm output similar to:&lt;br&gt;
Stage: Build&lt;br&gt;
Environment: Staging&lt;br&gt;
Finished: SUCCESS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdzqg3l8jjb48g05nq6wd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdzqg3l8jjb48g05nq6wd.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanations (Beginner Friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is a Parameterized Job?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A parameterized job lets users provide values when starting a build.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding values, Jenkins asks for them before running the job.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Stage = Build&lt;br&gt;
env = Staging&lt;/p&gt;

&lt;p&gt;These values become variables Jenkins can use during the build.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Create the String Parameter Stage?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A String Parameter allows users to type text.&lt;/p&gt;

&lt;p&gt;You are creating:&lt;/p&gt;

&lt;p&gt;Stage&lt;/p&gt;

&lt;p&gt;with default value:&lt;/p&gt;

&lt;p&gt;Build&lt;/p&gt;

&lt;p&gt;If the user does not change it, Jenkins automatically uses:&lt;/p&gt;

&lt;p&gt;Build&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Create the Choice Parameter env?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Choice Parameter provides a dropdown menu.&lt;/p&gt;

&lt;p&gt;Available options:&lt;/p&gt;

&lt;p&gt;Development&lt;br&gt;
Staging&lt;br&gt;
Production&lt;/p&gt;

&lt;p&gt;This prevents typing mistakes and ensures valid environments are selected.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Does the Shell Script Use Parameters?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Jenkins runs the job:&lt;/p&gt;

&lt;p&gt;echo "Stage: $Stage"&lt;br&gt;
echo "Environment: $env"&lt;/p&gt;

&lt;p&gt;Jenkins replaces:&lt;/p&gt;

&lt;p&gt;$Stage&lt;/p&gt;

&lt;p&gt;with the selected Stage value.&lt;/p&gt;

&lt;p&gt;and replaces:&lt;/p&gt;

&lt;p&gt;$env&lt;/p&gt;

&lt;p&gt;with the selected environment.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Stage = Build&lt;br&gt;
env = Staging&lt;/p&gt;

&lt;p&gt;Output becomes:&lt;/p&gt;

&lt;p&gt;Stage: Build&lt;br&gt;
Environment: Staging&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why Must You Use "Build with Parameters"?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A parameterized job requires values to be supplied.&lt;/p&gt;

&lt;p&gt;Therefore use:&lt;/p&gt;

&lt;p&gt;Build with Parameters&lt;/p&gt;

&lt;p&gt;instead of:&lt;/p&gt;

&lt;p&gt;Build Now&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-DevOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>kodekloud</category>
      <category>jenkins</category>
    </item>
    <item>
      <title>1.Jenkins Views</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Wed, 08 Jul 2026 23:30:00 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/1jenkins-views-3p4i</link>
      <guid>https://dev.to/thukhakyawe_cloud/1jenkins-views-3p4i</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;The DevOps team of xFusionCorp Industries is planning to create a number of Jenkins jobs for different tasks. So to easily manage the jobs within Jenkins UI they decided to create different views for all Jenkins jobs based on usage/nature of these jobs, - for example xfusion-crons view for all cron jobs. Based on the requirements shared below please perform the below mentioned task:&lt;/p&gt;

&lt;p&gt;Click on the Jenkins button on the top bar to access the Jenkins UI. Login using username admin and password Adm!n321.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a Jenkins job named xfusion-test-job.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure this job to run a simple bash command i.e echo "hello world!!".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a view named xfusion-crons (it must be a global view of type List View) and make sure xfusion-test-job and xfusion-cron-job (which is already present on Jenkins) jobs are listed under this new view.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schedule this newly created job to build periodically at every minute i.e * * * * * (please make sure to use the cron expression exactly same how it is mentioned here).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure the job builds successfully.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You might need to install some plugins and restart Jenkins service. So, we recommend clicking on Restart Jenkins when installation is complete and no jobs are running on plugin installation/update page i.e update centre. Also, Jenkins UI sometimes gets stuck when Jenkins service restarts in the back end. In this case please make sure to refresh the UI page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For these kind of scenarios requiring changes to be done in a web UI, please take screenshots so that you can share it with us for review in case your task is marked incomplete. You may also consider using a screen recording software such as loom.com to record and share your work.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Step 1: Log in to Jenkins&lt;br&gt;
Click the Jenkins button on the top bar.&lt;br&gt;
Login with:&lt;br&gt;
Username: admin&lt;br&gt;
Password: Adm!n321&lt;/p&gt;

&lt;p&gt;Step 2: Create the Jenkins Job&lt;br&gt;
From the Jenkins Home Dashboard (important: not from My Views), click New Item.&lt;br&gt;
Enter:&lt;br&gt;
xfusion-test-job&lt;br&gt;
Select Freestyle project.&lt;br&gt;
Click OK.&lt;/p&gt;

&lt;p&gt;Step 3: Configure the Build Trigger&lt;br&gt;
Open Configure for xfusion-test-job.&lt;br&gt;
Scroll to Build Triggers.&lt;br&gt;
Check Build periodically.&lt;br&gt;
Enter exactly:&lt;/p&gt;




&lt;p&gt;⚠️ Do not use:&lt;/p&gt;

&lt;p&gt;H * * * *&lt;br&gt;
H/1 * * * *&lt;/p&gt;

&lt;p&gt;The validator checks for the exact cron expression.&lt;/p&gt;

&lt;p&gt;Step 4: Configure the Build Step&lt;br&gt;
Scroll to the Build section.&lt;br&gt;
Click Add build step → Execute shell.&lt;br&gt;
Enter:&lt;br&gt;
echo "hello world!!"&lt;br&gt;
Click Save.&lt;/p&gt;

&lt;p&gt;Step 5: Create the Global View&lt;/p&gt;

&lt;p&gt;⚠️ Important: Create the view from the Jenkins Home Dashboard, not from My Views.&lt;/p&gt;

&lt;p&gt;Click the Jenkins logo to return to the main dashboard.&lt;br&gt;
Click + New View.&lt;br&gt;
Enter:&lt;br&gt;
xfusion-crons&lt;br&gt;
Select:&lt;br&gt;
List View&lt;br&gt;
Click Create.&lt;/p&gt;

&lt;p&gt;Step 6: Add Jobs to the View&lt;br&gt;
Open xfusion-crons.&lt;br&gt;
Click Edit View.&lt;br&gt;
Add these jobs:&lt;br&gt;
xfusion-test-job&lt;br&gt;
xfusion-cron-job&lt;br&gt;
Save.&lt;br&gt;
Verify both jobs appear in the view.&lt;/p&gt;

&lt;p&gt;Step 7: Build the Job&lt;br&gt;
Open xfusion-test-job.&lt;br&gt;
Click Build Now.&lt;br&gt;
Wait for the build to finish.&lt;/p&gt;

&lt;p&gt;Step 8: Verify Success&lt;br&gt;
Open the latest build.&lt;br&gt;
Click Console Output.&lt;br&gt;
Verify:&lt;br&gt;
hello world!!&lt;br&gt;
Finished: SUCCESS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk9b7ru21ush6afqltq0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk9b7ru21ush6afqltq0w.png" alt=" " width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanations (Beginner Friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why create xfusion-test-job?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Jenkins job is a task Jenkins can run automatically. This lab requires creating a new job.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use a Freestyle Project?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Freestyle projects are the simplest Jenkins jobs and are perfect for running shell commands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why add the cron schedule?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The schedule tells Jenkins when to run the job automatically.&lt;/p&gt;

&lt;p&gt;The expression:&lt;/p&gt;




&lt;p&gt;means:&lt;/p&gt;

&lt;p&gt;Every minute of every hour of every day&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why add Execute shell?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets Jenkins run Linux commands.&lt;/p&gt;

&lt;p&gt;The command:&lt;/p&gt;

&lt;p&gt;echo "hello world!!"&lt;/p&gt;

&lt;p&gt;simply prints:&lt;/p&gt;

&lt;p&gt;hello world!!&lt;/p&gt;

&lt;p&gt;to the build log.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why create xfusion-crons as a Global List View?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lab specifically requires:&lt;/p&gt;

&lt;p&gt;View name: xfusion-crons&lt;br&gt;
View type: List View&lt;br&gt;
Scope: Global&lt;/p&gt;

&lt;p&gt;Creating it from Jenkins Home ensures the validator can find it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I know the task is complete?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should have:&lt;/p&gt;

&lt;p&gt;✔ Job: xfusion-test-job&lt;/p&gt;

&lt;p&gt;✔ Build command:&lt;/p&gt;

&lt;p&gt;echo "hello world!!"&lt;/p&gt;

&lt;p&gt;✔ Global List View:&lt;/p&gt;

&lt;p&gt;xfusion-crons&lt;/p&gt;

&lt;p&gt;✔ Both jobs listed:&lt;/p&gt;

&lt;p&gt;xfusion-test-job&lt;br&gt;
xfusion-cron-job&lt;/p&gt;

&lt;p&gt;✔ Cron schedule:&lt;/p&gt;




&lt;p&gt;✔ Console Output:&lt;/p&gt;

&lt;p&gt;hello world!!&lt;br&gt;
Finished: SUCCESS&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-DevOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>kodekloud</category>
      <category>jenkins</category>
    </item>
    <item>
      <title>Day 14: Create a DVC Pipeline for Data Processing</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Mon, 06 Jul 2026 12:44:36 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/day-14-create-a-dvc-pipeline-for-data-processing-40n7</link>
      <guid>https://dev.to/thukhakyawe_cloud/day-14-create-a-dvc-pipeline-for-data-processing-40n7</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;The xFusionCorp Industries ML team utilizes DVC pipelines to ensure the reproducibility of data processing. The fraud-detection project has the processing scripts and raw data in place but does not yet define a pipeline. Define a two-stage DVC pipeline so the data processing runs reproducibly from start to finish with dvc repro.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A project exists at /root/code/fraud-detection/ with DVC initialised. The scripts are at src/data/process_data.py and src/data/split_data.py, and the raw input is at data/raw/transactions.csv. Do not modify the Python files or the input data.

Create a dvc.yaml defining two stages (use dvc stage add, or write the YAML directly):
    process_data – runs python3 src/data/process_data.py; depends on data/raw/transactions.csv and src/data/process_data.py; produces data/processed/clean_transactions.csv.
    split_data – runs python3 src/data/split_data.py; depends on data/processed/clean_transactions.csv (the upstream stage's output, so DVC chains the stages) and src/data/split_data.py; produces data/processed/train.csv and data/processed/test.csv.

Run the pipeline with dvc repro so both stages execute in order and dvc.lock is written.

After your changes, dvc status must report no stale stages.

Use python3 (not python) in the stage commands. Once the pipeline is valid, dvc dag prints the dependency graph showing how the two stages chain together.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Step 1: Move into the repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/code/fraud-detection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Verify the required files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find src
find data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have:&lt;/p&gt;

&lt;p&gt;src&lt;br&gt;
src/data&lt;br&gt;
src/data/process_data.py&lt;br&gt;
src/data/split_data.py&lt;br&gt;
data&lt;br&gt;
data/raw&lt;br&gt;
data/raw/transactions.csv&lt;/p&gt;

&lt;p&gt;Step 3: Create the first DVC stage (process_data)&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc stage add &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-n&lt;/span&gt; process_data &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; data/raw/transactions.csv &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; src/data/process_data.py &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-o&lt;/span&gt; data/processed/clean_transactions.csv &lt;span class="se"&gt;\&lt;/span&gt;
python3 src/data/process_data.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation of options&lt;br&gt;
Option  Meaning&lt;br&gt;
-n  Stage name&lt;br&gt;
-d  Dependency&lt;br&gt;
-o  Output&lt;br&gt;
Last argument   Command to execute&lt;/p&gt;

&lt;p&gt;Step 4: Create the second DVC stage (split_data)&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc stage add &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-n&lt;/span&gt; split_data &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; data/processed/clean_transactions.csv &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; src/data/split_data.py &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-o&lt;/span&gt; data/processed/train.csv &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-o&lt;/span&gt; data/processed/test.csv &lt;span class="se"&gt;\&lt;/span&gt;
python3 src/data/split_data.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the dependency:&lt;/p&gt;

&lt;p&gt;data/processed/clean_transactions.csv&lt;/p&gt;

&lt;p&gt;is the output from Stage 1. This automatically links the stages together.&lt;/p&gt;

&lt;p&gt;Step 5: Verify dvc.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;dvc.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected structure:&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;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;process_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/data/process_data.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/raw/transactions.csv&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/data/process_data.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/clean_transactions.csv&lt;/span&gt;
  &lt;span class="na"&gt;split_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 src/data/split_data.py&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/clean_transactions.csv&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/data/split_data.py&lt;/span&gt;
    &lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/test.csv&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data/processed/train.csv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 6: Run the pipeline&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc repro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Running stage 'process_data':                                                  
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 src/data/process_data.py
&lt;span class="go"&gt;Processed 15 rows
Generating lock file 'dvc.lock'                                                
Updating lock file 'dvc.lock'

Running stage 'split_data':                                                    
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 src/data/split_data.py
&lt;span class="go"&gt;Train: 12 rows, Test: 3 rows
Updating lock file 'dvc.lock'                                                  

To track the changes with git, run:

        git add dvc.lock data/processed/.gitignore

To enable auto staging, run:

        dvc config core.autostage true
Use `dvc push` to send your updates to remote storage.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 7: Verify dvc.lock&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data
dvc.lock
dvc.yaml
src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 8: Check pipeline status&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;Data and pipelines are up to date.&lt;/p&gt;

&lt;p&gt;This satisfies the lab requirement of having no stale stages.&lt;/p&gt;

&lt;p&gt;Step 9: Display the dependency graph&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc dag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;WARNING: Unable to find `less` in the PATH. Check out &amp;lt;https://man.dvc.org/pipeline/show&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;more info.
&lt;span class="go"&gt;+--------------+ 
| process_data | 
+--------------+ 
        *        
        *        
        *        
 +------------+  
 | split_data |  
 +------------+ 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanation (Beginner Friendly)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is a DVC Pipeline?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A DVC pipeline defines a sequence of steps for processing data. Each step is called a stage.&lt;/p&gt;

&lt;p&gt;Instead of manually running scripts one by one, DVC knows:&lt;/p&gt;

&lt;p&gt;which script to run&lt;br&gt;
what input files it needs&lt;br&gt;
what output files it creates&lt;br&gt;
which stage depends on another&lt;/p&gt;

&lt;p&gt;This makes the workflow reproducible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why do we create two stages?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project has two separate tasks:&lt;/p&gt;

&lt;p&gt;Stage 1: Process the raw data&lt;/p&gt;

&lt;p&gt;Input:&lt;/p&gt;

&lt;p&gt;data/raw/transactions.csv&lt;/p&gt;

&lt;p&gt;Script:&lt;/p&gt;

&lt;p&gt;src/data/process_data.py&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;data/processed/clean_transactions.csv&lt;/p&gt;

&lt;p&gt;This stage cleans or prepares the raw dataset.&lt;/p&gt;

&lt;p&gt;Stage 2: Split the processed data&lt;/p&gt;

&lt;p&gt;Input:&lt;/p&gt;

&lt;p&gt;data/processed/clean_transactions.csv&lt;/p&gt;

&lt;p&gt;Script:&lt;/p&gt;

&lt;p&gt;src/data/split_data.py&lt;/p&gt;

&lt;p&gt;Outputs:&lt;/p&gt;

&lt;p&gt;data/processed/train.csv&lt;br&gt;
data/processed/test.csv&lt;/p&gt;

&lt;p&gt;This stage creates the training and testing datasets.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How are the stages connected?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output of the first stage becomes the input of the second stage:&lt;/p&gt;

&lt;p&gt;transactions.csv&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
process_data&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
clean_transactions.csv&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
split_data&lt;br&gt;
      ├──────────┐&lt;br&gt;
      ▼          ▼&lt;br&gt;
 train.csv   test.csv&lt;/p&gt;

&lt;p&gt;This dependency allows DVC to automatically execute the stages in the correct order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does dvc repro do?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The command:&lt;/p&gt;

&lt;p&gt;dvc repro&lt;/p&gt;

&lt;p&gt;checks the pipeline and runs any stages that need to be executed.&lt;/p&gt;

&lt;p&gt;In this lab:&lt;/p&gt;

&lt;p&gt;process_data runs first because it depends on the raw dataset.&lt;br&gt;
After clean_transactions.csv is created, split_data runs because its dependency is now available.&lt;/p&gt;

&lt;p&gt;You don't need to run the Python scripts manually—DVC handles the execution order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is dvc.lock?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a successful pipeline run, DVC creates:&lt;/p&gt;

&lt;p&gt;dvc.lock&lt;/p&gt;

&lt;p&gt;This file records:&lt;/p&gt;

&lt;p&gt;the exact command used&lt;br&gt;
the dependencies&lt;br&gt;
the output files&lt;br&gt;
checksums (hashes) of inputs and outputs&lt;/p&gt;

&lt;p&gt;It ensures that the pipeline can be reproduced exactly in the future.&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-MLOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>100daysofmlops</category>
      <category>kodekloud</category>
    </item>
    <item>
      <title>Day 13: Pull DVC-Tracked Data from Remote</title>
      <dc:creator>Thu Kha Kyawe</dc:creator>
      <pubDate>Mon, 06 Jul 2026 12:40:45 +0000</pubDate>
      <link>https://dev.to/thukhakyawe_cloud/day-13-pull-dvc-tracked-data-from-remote-50l1</link>
      <guid>https://dev.to/thukhakyawe_cloud/day-13-pull-dvc-tracked-data-from-remote-50l1</guid>
      <description>&lt;h1&gt;
  
  
  Lab Information
&lt;/h1&gt;

&lt;p&gt;A new xFusionCorp Industries team member has cloned the fraud-detection repository onto a fresh machine. The DVC remote is already configured to point at the team's SeaweedFS bucket, but dvc pull is failing. Diagnose the cause, correct the configuration, and pull the dataset.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A cloned project exists at /root/code/fraud-detection/ with DVC initialised, the data/raw/transactions.csv.dvc pointer file present, but the dataset itself missing from disk and from the local DVC cache.

SeaweedFS is already running on the controlplane and the dataset has already been pushed to the dvc-storage bucket—open the SeaweedFS Filer button at the top of the lab and navigate to /buckets/dvc-storage/ to confirm that the object is there.
    S3 endpoint: http://localhost:8333
    Credentials: weedadmin / weedadmin123

Review .dvc/config and correct everything that prevents dvc pull from authenticating against SeaweedFS.

After the fix, the s3 remote must use:
    The access key (access_key_id) weedadmin
    The secret key (secret_access_key) weedadmin123.

Pull the dataset. After the pull, data/raw/transactions.csv must be present on disk and its content must match the hash recorded in the .dvc pointer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h1&gt;
  
  
  Lab Solutions
&lt;/h1&gt;

&lt;p&gt;✅ Part 1: Lab Step-by-Step Guidelines&lt;/p&gt;

&lt;p&gt;Step 1: Move into the repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/code/fraud-detection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Verify the dataset is missing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; data/raw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;/p&gt;

&lt;p&gt;transactions.csv.dvc&lt;/p&gt;

&lt;p&gt;but not:&lt;/p&gt;

&lt;p&gt;transactions.csv&lt;/p&gt;

&lt;p&gt;Step 3: Inspect the DVC configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .dvc/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for the s3 remote configuration.&lt;/p&gt;

&lt;p&gt;You are specifically looking for incorrect credentials.&lt;/p&gt;

&lt;p&gt;Step 4: Fix the SeaweedFS credentials&lt;/p&gt;

&lt;p&gt;The lab requires:&lt;/p&gt;

&lt;p&gt;Setting             Value&lt;br&gt;
access_key_id       weedadmin&lt;br&gt;
secret_access_key   weedadmin123&lt;/p&gt;

&lt;p&gt;Configure them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc remote modify s3 access_key_id weedadmin
dvc remote modify s3 secret_access_key weedadmin123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Verify the configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .dvc/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[core]&lt;/span&gt;
    &lt;span class="py"&gt;remote&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;s3&lt;/span&gt;
&lt;span class="nn"&gt;['remote "s3"']&lt;/span&gt;
    &lt;span class="py"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;s3://dvc-storage&lt;/span&gt;
    &lt;span class="py"&gt;endpointurl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8333&lt;/span&gt;
    &lt;span class="py"&gt;access_key_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;weedadmin&lt;/span&gt;
    &lt;span class="py"&gt;secret_access_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;weedadmin123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 6: Pull the dataset&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;root@controlplane fraud-detection on  main [!] ➜  dvc pull
Collecting                                           |1.00 [00:00,  730entry/s]
Fetching
Building workspace index                             |2.00 [00:00,  661entry/s]
Comparing indexes                                   |4.00 [00:00, 2.90kentry/s]
Applying changes                                     |1.00 [00:00, 1.18kfile/s]
A       data/raw/transactions.csv
1 file fetched and 1 file added
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 7: Verify the dataset exists&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; data/raw/transactions.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;data/raw/transactions.csv&lt;/p&gt;

&lt;p&gt;Step 8: Verify DVC status&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dvc status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;/p&gt;

&lt;p&gt;Data and pipelines are up to date.&lt;/p&gt;

&lt;p&gt;Step 9: Verify integrity&lt;/p&gt;

&lt;p&gt;Check the DVC pointer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;data/raw/transactions.csv.dvc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&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="s"&gt;root@controlplane fraud-detection on  main [!] ➜  cat data/raw/transactions.csv.dvc&lt;/span&gt;
&lt;span class="na"&gt;outs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;md5&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;555f037ee350464f52122d087f28e857&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;446&lt;/span&gt;
  &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;md5&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;transactions.csv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🧠 Part 2: Simple Step-by-Step Explanation (Beginner Friendly)&lt;/p&gt;

&lt;p&gt;What happened?&lt;/p&gt;

&lt;p&gt;A teammate cloned the Git repository onto a new machine.&lt;/p&gt;

&lt;p&gt;Git downloaded:&lt;/p&gt;

&lt;p&gt;transactions.csv.dvc&lt;/p&gt;

&lt;p&gt;but not:&lt;/p&gt;

&lt;p&gt;transactions.csv&lt;/p&gt;

&lt;p&gt;because DVC-managed data is stored separately from Git.&lt;/p&gt;

&lt;p&gt;Why is the file missing?&lt;/p&gt;

&lt;p&gt;Git only stores the small pointer file:&lt;/p&gt;

&lt;p&gt;transactions.csv.dvc&lt;/p&gt;

&lt;p&gt;The actual dataset lives in SeaweedFS:&lt;/p&gt;

&lt;p&gt;SeaweedFS Bucket&lt;br&gt;
└── dvc-storage&lt;/p&gt;

&lt;p&gt;To download it, DVC must connect to the remote storage.&lt;/p&gt;

&lt;p&gt;Why is dvc pull failing?&lt;/p&gt;

&lt;p&gt;The lab says:&lt;/p&gt;

&lt;p&gt;Review .dvc/config and correct everything that prevents dvc pull from authenticating.&lt;/p&gt;

&lt;p&gt;This means the most likely issue is incorrect credentials.&lt;/p&gt;

&lt;p&gt;Required credentials:&lt;/p&gt;

&lt;p&gt;access_key_id = weedadmin&lt;br&gt;
secret_access_key = weedadmin123&lt;/p&gt;

&lt;p&gt;If either value is wrong, DVC cannot access the SeaweedFS bucket.&lt;/p&gt;

&lt;p&gt;What does dvc pull do?&lt;/p&gt;

&lt;p&gt;When you run:&lt;/p&gt;

&lt;p&gt;dvc pull&lt;/p&gt;

&lt;p&gt;DVC:&lt;/p&gt;

&lt;p&gt;Reads transactions.csv.dvc&lt;br&gt;
Finds the file hash&lt;br&gt;
Connects to SeaweedFS&lt;br&gt;
Downloads the matching object&lt;br&gt;
Restores:&lt;br&gt;
data/raw/transactions.csv&lt;/p&gt;

&lt;p&gt;onto your machine&lt;/p&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Resources &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  📦 Full Code Repository: &lt;a href="https://github.com/thukhakyawe/100-Days-Of-MLOps-KodeKloud-Challenges-Solutions" rel="noopener noreferrer"&gt;KodeKloud Learning Labs&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💬 Join Discussion: &lt;a href="https://dev.to/thukhakyawe_cloud"&gt;DEV Community&lt;/a&gt; - Share your thoughts and questions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  💼 Let's Connect: &lt;a href="https://www.linkedin.com/in/thukhakyawe/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; - I'd love to connect with you
&lt;/h5&gt;




&lt;h5&gt;
  
  
  &lt;strong&gt;Credits&lt;/strong&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • All labs are from: &lt;a href="https://kodekloud.com/" rel="noopener noreferrer"&gt;KodeKloud&lt;/a&gt;
&lt;/h5&gt;

&lt;h5&gt;
  
  
  • I sincerely appreciate your provision of these valuable resources.
&lt;/h5&gt;




</description>
      <category>100daysofmlops</category>
      <category>kodekloud</category>
    </item>
  </channel>
</rss>
