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

De la WikiLabs
Jump to navigationJump to search
Linia 92: Linia 92:
  
 
== Phase 5: Continuous Deployment (CD) ==
 
== Phase 5: Continuous Deployment (CD) ==
Once the code hits the <code>main</code> branch, we want to automatically package it for an Over-The-Air (OTA) firmware update.
+
Once the code hits the <code>main</code> branch, we want to handle two different types of deployments: an automated OTA release (Pull), and an on-demand Edge deployment (Push).
  
'''Your Challenge (Part 3):'''
+
'''Your Challenge (Part 3): Automated OTA Release'''
Add a final job named <code>release_ota_firmware</code>:
+
Add a job named <code>release_ota_firmware</code>:
 
# Stage: <code>deploy</code>
 
# Stage: <code>deploy</code>
 
# Tags: <code>local-embedded</code>
 
# Tags: <code>local-embedded</code>
Linia 102: Linia 102:
 
#* <code>mv build/unit_tests build/firmware_v1.bin</code>
 
#* <code>mv build/unit_tests build/firmware_v1.bin</code>
 
#* <code>echo "CRYPTOGRAPHIC_SIGNATURE_OK" >> 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>.
+
# '''Rules:''' We ONLY want to release firmware automatically 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.
 
# '''Artifacts:''' Save <code>build/firmware_v1.bin</code> 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!
+
'''Your Challenge (Part 4): On-Demand Push Deployment'''
 +
Sometimes we need to instantly push an update to a specific machine (e.g., a prototype in the lab) without waiting for it to poll. We will simulate an SSH deployment using pipeline variables.  
  
----
+
Add another job named <code>deploy_to_edge_device</code>:
 +
# Stage: <code>deploy</code>
 +
# Tags: <code>local-embedded</code>
 +
# <code>dependencies:</code> Pull from <code>compile_firmware</code>.
 +
# '''Rules:''' We want this to be an "On-Demand" job that requires a human to click a play button. Add a <code>rules:</code> section with <code>- when: manual</code>.
 +
# <code>script:</code> Simulate securely pushing the binary to a specific IP address using an environment variable (<code>$TARGET_IP</code>):
 +
#* <code>echo "Connecting to Edge Device at $TARGET_IP..."</code>
 +
#* <code>echo "scp build/unit_tests admin@$TARGET_IP:/opt/smart-oven/bin/"</code>
 +
#* <code>echo "Deployment to $TARGET_IP successful!"</code>
 +
 
 +
'''Test the Deployments:'''
 +
# Push your code to <code>main</code>.
 +
# You will see the <code>release_ota_firmware</code> job run automatically.
 +
# The <code>deploy_to_edge_device</code> job will be paused (marked with a "Play" icon).
 +
# Click the Play icon, and GitLab will allow you to manually input a value for <code>TARGET_IP</code> before executing the push!
  
 
== Phase 6: Cleanup ==
 
== Phase 6: Cleanup ==

Versiunea de la data 19 aprilie 2026 17:08

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 handle two different types of deployments: an automated OTA release (Pull), and an on-demand Edge deployment (Push).

Your Challenge (Part 3): Automated OTA Release Add a 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 automatically 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.

Your Challenge (Part 4): On-Demand Push Deployment Sometimes we need to instantly push an update to a specific machine (e.g., a prototype in the lab) without waiting for it to poll. We will simulate an SSH deployment using pipeline variables.

Add another job named deploy_to_edge_device:

  1. Stage: deploy
  2. Tags: local-embedded
  3. dependencies: Pull from compile_firmware.
  4. Rules: We want this to be an "On-Demand" job that requires a human to click a play button. Add a rules: section with - when: manual.
  5. script: Simulate securely pushing the binary to a specific IP address using an environment variable ($TARGET_IP):
    • echo "Connecting to Edge Device at $TARGET_IP..."
    • echo "scp build/unit_tests admin@$TARGET_IP:/opt/smart-oven/bin/"
    • echo "Deployment to $TARGET_IP successful!"

Test the Deployments:

  1. Push your code to main.
  2. You will see the release_ota_firmware job run automatically.
  3. The deploy_to_edge_device job will be paused (marked with a "Play" icon).
  4. Click the Play icon, and GitLab will allow you to manually input a value for TARGET_IP before executing the push!

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.