Diferență între revizuiri ale paginii „SDPT Lab 6”

De la WikiLabs
Jump to navigationJump to search
(Pagină nouă: = Week 6 Lab Activity: Continuous Integration (CI) with GitLab = == Objective == Today, we automate everything. You will transition from compiling code on your laptop to architect...)
 
Linia 1: Linia 1:
= Week 6 Lab Activity: Continuous Integration (CI) with GitLab =
+
= Week 6 Lab Activity: CI/CD Pipelines & Custom Runners =
  
 
== Objective ==
 
== Objective ==
Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI pipeline. You will use your Docker image from last week to cross-compile your C++ code, run your Google Tests in QEMU, and configure GitLab to mechanically prevent broken code from ever reaching the <code>main</code> branch.
+
Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI/CD pipeline.  
  
We will accomplish this in four phases:
+
We will accomplish this in six phases:
 
# '''Repository Setup:''' Migrating your code to GitLab.
 
# '''Repository Setup:''' Migrating your code to GitLab.
# '''The Build Stage:''' Writing your first CI job and generating Artifacts.
+
# '''Infrastructure:''' Spinning up and registering your own local GitLab Runner via Docker.
# '''The Test Stage:''' Consuming Artifacts and failing the pipeline on bad tests.
+
# '''Continuous Integration (Build):''' Writing your first CI job and generating Artifacts.
# '''Merge Checks:''' Enforcing quality control via Merge Requests.
+
# '''Continuous Integration (Test):''' Consuming Artifacts and testing via QEMU.
 +
# '''Continuous Deployment (CD):''' Creating a simulated OTA firmware release restricted to the <code>main</code> branch.
 +
# '''Cleanup:''' Deregistering and destroying your local runner.
  
 
----
 
----
  
 
== Phase 1: Repository Setup ==
 
== Phase 1: Repository Setup ==
To use GitLab CI, your code must live on a GitLab server.
 
 
 
'''1. Create a Project:'''
 
'''1. Create a Project:'''
 
Log into GitLab and create a new blank project named <code>sdpt-smart-oven</code>. Uncheck "Initialize repository with a README".
 
Log into GitLab and create a new blank project named <code>sdpt-smart-oven</code>. Uncheck "Initialize repository with a README".
Linia 31: Linia 31:
 
----
 
----
  
== Phase 2: The Build Stage & Artifacts ==
+
== Phase 2: Registering a Local Runner ==
We will now tell the GitLab Runner how to build our code using the Docker image you designed last week.
+
GitLab provides shared runners, but embedded systems often require custom hardware or specific toolchains. We will host our own Runner!
  
'''Your Challenge:'''
+
'''1. Get Your Registration Token:'''
Create a file named exactly <code>.gitlab-ci.yml</code> in the root of your project. Write the YAML to meet these specifications:
+
In your GitLab project, go to '''Settings''' -> '''CI/CD'''. Expand the '''Runners''' section. Under "Project runners", click "New project runner". Add the tag <code>local-embedded</code> and click Create. Copy the '''registration token''' it gives you.
  
# '''Image:''' Set the global <code>image:</code> to the Docker registry URL of the ARM image you built in Week 5 (or use a public equivalent provided by the instructor, e.g., <code>registry.gitlab.com/sdpt-course/arm-build-env:latest</code>).
+
'''2. Start the Runner via Docker:'''
# '''Stages:''' Define two stages: <code>build</code> and <code>test</code>.
+
On your laptop terminal, run a background Docker container to act as your runner. (We mount the Docker socket so the runner can spawn its own containers!)
 +
<syntaxhighlight lang="bash">
 +
docker run -d --name my-local-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
 +
</syntaxhighlight>
 +
 
 +
'''3. Register the Runner:'''
 +
Now, execute the registration command inside the running container:
 +
<syntaxhighlight lang="bash">
 +
docker exec -it my-local-runner gitlab-runner register
 +
</syntaxhighlight>
 +
* '''GitLab instance URL:''' <code>https://gitlab.com/</code>
 +
* '''Registration token:''' (Paste your token from step 1)
 +
* '''Description:''' My Laptop Runner
 +
* '''Tags:''' <code>local-embedded</code>
 +
* '''Executor:''' <code>docker</code>
 +
* '''Default image:''' <code>ubuntu:22.04</code>
 +
 
 +
Refresh your GitLab Runners page. You should see a green circle indicating your local runner is alive and listening for jobs!
 +
 
 +
----
 +
 
 +
== Phase 3: The Build Stage & Artifacts ==
 +
We will now tell your Runner how to build our code. Create a file named exactly <code>.gitlab-ci.yml</code> in your project root.
 +
 
 +
'''Your Challenge (Part 1):'''
 +
# '''Image:''' Set <code>image:</code> to the ARM Docker image you built last week.
 +
# '''Stages:''' Define three stages: <code>build</code>, <code>test</code>, and <code>deploy</code>.
 
# '''The Build Job:''' Create a job named <code>compile_firmware</code>.
 
# '''The Build Job:''' Create a job named <code>compile_firmware</code>.
 
#* Assign it to the <code>build</code> stage.
 
#* Assign it to the <code>build</code> stage.
#* In the <code>script</code> section, create a build folder, run CMake for the <code>aarch64</code> compiler, and run <code>make</code>.
+
#* Use <code>tags: [local-embedded]</code> to force this job to run on YOUR laptop's runner.
# '''Artifacts:''' Tell GitLab to save the <code>build/</code> directory as an artifact that expires in 1 hour. (If you forget this, your compiled binary will be deleted before the test stage starts!)
+
#* In the <code>script</code>, run CMake for <code>aarch64</code> and run <code>make</code>.
 +
#* Create <code>artifacts</code> to save the <code>build/</code> directory (expire in 1 hour).
  
Commit and push this file. Go to your GitLab project -> '''Build''' -> '''Pipelines'''. You should see your pipeline running! Click on it to watch the live terminal output of the GitLab Runner.
+
Commit and push. Watch the pipeline in GitLab. Your laptop's fan might spin up because *your* Docker daemon is doing the heavy lifting!
  
 
----
 
----
  
== Phase 3: The Test Stage ==
+
== Phase 4: The Test Stage & Merge Checks ==
Once your build job turns green, it's time to test the artifact.
+
'''Your Challenge (Part 2):'''
 
+
Add a job named <code>verify_logic</code>:
'''Update your YAML:'''
+
# Stage: <code>test</code>
Add a second job named <code>verify_logic</code> to your <code>.gitlab-ci.yml</code>:
+
# Tags: <code>local-embedded</code>
# Assign it to the <code>test</code> stage.
+
# <code>dependencies:</code> Require the artifacts from <code>compile_firmware</code>.
# Use the <code>dependencies:</code> keyword to explicitly require the artifacts from <code>compile_firmware</code>.
+
# <code>script:</code> Navigate to <code>build/</code> and execute tests using QEMU (<code>qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests</code>).
# In the <code>script</code> section, navigate to the <code>build/</code> directory and execute your tests using QEMU (<code>qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests</code>).
 
  
Push the updated YAML. Watch the pipeline. The Runner will download the compiled binary from the previous stage and execute your tests!
+
'''Test the Block:'''
 +
# Go to GitLab '''Settings''' -> '''Merge Requests''' -> Check "Pipelines must succeed".
 +
# Create a new branch: <code>git checkout -b feature/broken-math</code>
 +
# Break an assertion in your C++ tests and push the branch.
 +
# Open a Merge Request. Watch the test stage fail and observe the Merge button physically lock you out! Fix the code, push again, and Merge it.
  
 
----
 
----
  
== Phase 4: Merge Checks and Failure (The DevOps Climax) ==
+
== Phase 5: Continuous Deployment (CD) ==
A pipeline is useless if developers can just bypass it. We will now configure GitLab to block bad code.
+
Once the code hits the <code>main</code> branch, we want to automatically package it for an Over-The-Air (OTA) firmware update.
  
'''1. Protect the Main Branch:'''
+
'''Your Challenge (Part 3):'''
In GitLab, go to '''Settings''' -> '''Merge Requests'''.  
+
Add a final job named <code>release_ota_firmware</code>:
Scroll down to '''Merge checks''' and check the box that says: ''"Pipelines must succeed"''. Save changes.
+
# Stage: <code>deploy</code>
 +
# Tags: <code>local-embedded</code>
 +
# <code>dependencies:</code> Pull from <code>compile_firmware</code>.
 +
# <code>script:</code> Rename your binary to a release format and simulate cryptographically signing it:
 +
#* <code>mv build/unit_tests build/firmware_v1.bin</code>
 +
#* <code>echo "CRYPTOGRAPHIC_SIGNATURE_OK" >> build/firmware_v1.bin</code>
 +
# '''Rules:''' We ONLY want to release firmware from the main branch! Add a <code>rules:</code> section with <code>- if: '$CI_COMMIT_BRANCH == "main"'</code>.
 +
# '''Artifacts:''' Save <code>build/firmware_v1.bin</code> as an artifact that never expires.
  
'''2. Create a Feature Branch:'''
+
Push to main. You should see a 3-stage pipeline complete successfully. You can now download your final "signed" firmware directly from the GitLab UI!
Back on your laptop terminal, create a new branch:
 
<syntaxhighlight lang="bash">
 
git checkout -b feature/broken-sensor
 
</syntaxhighlight>
 
  
'''3. Sabotage the Code!'''
+
----
Open your <code>test_oven.cpp</code> file. Intentionally change a mathematical assertion so that it will fail (e.g., change <code>EXPECT_EQ(temp, 100);</code> to <code>EXPECT_EQ(temp, 999);</code>).
 
  
'''4. Push and Open a Merge Request:'''
+
== Phase 6: Cleanup ==
Commit your broken test and push the branch to GitLab.
+
To prevent your runner from polling GitLab forever and draining your laptop battery, gracefully shut it down and remove it:
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
git commit -am "feat: updated sensor logic (with bugs)"
+
docker stop my-local-runner
git push -u origin feature/broken-sensor
+
docker rm my-local-runner
 
</syntaxhighlight>
 
</syntaxhighlight>
In GitLab, open a '''Merge Request''' from your feature branch into <code>main</code>.
+
In the GitLab UI, go back to Settings -> CI/CD -> Runners, and delete the offline runner.
 
 
'''5. Observe the Block:'''
 
Wait for the pipeline to run. The Build stage will pass, but the Test stage will turn RED because Google Test caught your broken math.
 
Look at the Merge Request page. '''The Merge button is physically disabled!''' GitLab has successfully protected your production code from human error.
 
 
 
'''6. Fix and Merge:'''
 
Fix the test on your laptop, commit, and push again. The pipeline will automatically re-run, turn green, and unlock the Merge button. Click Merge!
 
  
 
----
 
----
 
=== Assignment Submission ===
 
=== Assignment Submission ===
Upload '''ONLY''' your finalized <code>.gitlab-ci.yml</code> to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, and QEMU execution.
+
Upload '''ONLY''' your finalized <code>.gitlab-ci.yml</code> to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, custom runner routing, and deployment rules.

Versiunea de la data 19 aprilie 2026 17:05

Week 6 Lab Activity: CI/CD Pipelines & Custom Runners

Objective

Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI/CD pipeline.

We will accomplish this in six phases:

  1. Repository Setup: Migrating your code to GitLab.
  2. Infrastructure: Spinning up and registering your own local GitLab Runner via Docker.
  3. Continuous Integration (Build): Writing your first CI job and generating Artifacts.
  4. Continuous Integration (Test): Consuming Artifacts and testing via QEMU.
  5. Continuous Deployment (CD): Creating a simulated OTA firmware release restricted to the main branch.
  6. Cleanup: Deregistering and destroying your local runner.

Phase 1: Repository Setup

1. Create a Project: Log into GitLab and create a new blank project named sdpt-smart-oven. Uncheck "Initialize repository with a README".

2. Push Your Code: Open your terminal on your laptop, navigate to your Week 5 project folder, and push your code to this new repository.

git init
git branch -m main
git remote add origin https://gitlab.com/<your-username>/sdpt-smart-oven.git
git add .
git commit -m "Initial commit: Oven Controller with CMake and Docker"
git push -u origin main

Phase 2: Registering a Local Runner

GitLab provides shared runners, but embedded systems often require custom hardware or specific toolchains. We will host our own Runner!

1. Get Your Registration Token: In your GitLab project, go to Settings -> CI/CD. Expand the Runners section. Under "Project runners", click "New project runner". Add the tag local-embedded and click Create. Copy the registration token it gives you.

2. Start the Runner via Docker: On your laptop terminal, run a background Docker container to act as your runner. (We mount the Docker socket so the runner can spawn its own containers!)

docker run -d --name my-local-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest

3. Register the Runner: Now, execute the registration command inside the running container:

docker exec -it my-local-runner gitlab-runner register
  • GitLab instance URL: https://gitlab.com/
  • Registration token: (Paste your token from step 1)
  • Description: My Laptop Runner
  • Tags: local-embedded
  • Executor: docker
  • Default image: ubuntu:22.04

Refresh your GitLab Runners page. You should see a green circle indicating your local runner is alive and listening for jobs!


Phase 3: The Build Stage & Artifacts

We will now tell your Runner how to build our code. Create a file named exactly .gitlab-ci.yml in your project root.

Your Challenge (Part 1):

  1. Image: Set image: to the ARM Docker image you built last week.
  2. Stages: Define three stages: build, test, and deploy.
  3. The Build Job: Create a job named compile_firmware.
    • Assign it to the build stage.
    • Use tags: [local-embedded] to force this job to run on YOUR laptop's runner.
    • In the script, run CMake for aarch64 and run make.
    • Create artifacts to save the build/ directory (expire in 1 hour).

Commit and push. Watch the pipeline in GitLab. Your laptop's fan might spin up because *your* Docker daemon is doing the heavy lifting!


Phase 4: The Test Stage & Merge Checks

Your Challenge (Part 2): Add a job named verify_logic:

  1. Stage: test
  2. Tags: local-embedded
  3. dependencies: Require the artifacts from compile_firmware.
  4. script: Navigate to build/ and execute tests using QEMU (qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests).

Test the Block:

  1. Go to GitLab Settings -> Merge Requests -> Check "Pipelines must succeed".
  2. Create a new branch: git checkout -b feature/broken-math
  3. Break an assertion in your C++ tests and push the branch.
  4. Open a Merge Request. Watch the test stage fail and observe the Merge button physically lock you out! Fix the code, push again, and Merge it.

Phase 5: Continuous Deployment (CD)

Once the code hits the main branch, we want to automatically package it for an Over-The-Air (OTA) firmware update.

Your Challenge (Part 3): Add a final job named release_ota_firmware:

  1. Stage: deploy
  2. Tags: local-embedded
  3. dependencies: Pull from compile_firmware.
  4. script: Rename your binary to a release format and simulate cryptographically signing it:
    • mv build/unit_tests build/firmware_v1.bin
    • echo "CRYPTOGRAPHIC_SIGNATURE_OK" >> build/firmware_v1.bin
  5. Rules: We ONLY want to release firmware from the main branch! Add a rules: section with - if: '$CI_COMMIT_BRANCH == "main"'.
  6. Artifacts: Save build/firmware_v1.bin as an artifact that never expires.

Push to main. You should see a 3-stage pipeline complete successfully. You can now download your final "signed" firmware directly from the GitLab UI!


Phase 6: Cleanup

To prevent your runner from polling GitLab forever and draining your laptop battery, gracefully shut it down and remove it:

docker stop my-local-runner
docker rm my-local-runner

In the GitLab UI, go back to Settings -> CI/CD -> Runners, and delete the offline runner.


Assignment Submission

Upload ONLY your finalized .gitlab-ci.yml to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, custom runner routing, and deployment rules.