-
Notifications
You must be signed in to change notification settings - Fork 0
[EMB-115] Migrate package release from Cloudsmith to GAR #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
jellespijker
wants to merge
16
commits into
main
Choose a base branch
from
EMB-115_migrate_to_gar
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This commit migrates the Debian package release process from Cloudsmith to Google Artifact Registry (GAR). The `release_pkg.yml` workflow has been updated to: - Authenticate with Google Cloud using Workload Identity Federation. - Use `gcloud artifacts apt upload` to publish packages. - Automatically extract package metadata from the `.deb` file. - Generate a detailed job summary with instructions on how to install the package from the new GAR repository. The now-unused `cloudsmith.Dockerfile` has been removed.
This commit refactors the CI versioning logic to fully support Semantic Versioning 2.0. The version generation logic has been extracted from the `prepare_env.yml` workflow into a dedicated, reusable, and testable shell script. Key changes include: - A new script `generate_semver_version.sh` that determines the `RELEASE_VERSION` and `RELEASE_REPO` based on the Git context (branch, tag, PR). - Support for `alpha`, `beta`, and `rc` pre-release tags, in addition to final release tags. - Automatic patch version bumping for development and nightly builds based on the latest Git tag. - Nightly builds for master branch merges now produce versions like `X.Y.Z-alpha.0+YYYYMMDD.branch.sha`. - Development builds for pull requests and feature branches generate versions like `X.Y.Z-alpha.0+sha`. - A comprehensive test script, `test_generate_semver_version.sh`, is introduced to validate the versioning logic across various scenarios. - The `prepare_env` workflow now includes a summary step that clearly documents the generated version, target repository, and the versioning strategy for better visibility in GitHub Actions.
The `release_pkg` workflow was hardcoded to find `.deb` packages in the `./dist` directory. This change removes that assumption, making the workflow search for packages in the current working directory. This allows for more flexibility in the preceding build job, which no longer needs to place artifacts in a `dist` folder. The documentation in the job summary has been updated accordingly.
Not needed anymore and only clutter the logs
This commit refactors the GitHub Actions workflows to use a new centralized build script located in the `embedded-workflows` repository. Key changes include: - Updating `build.yml`, `unit_test.yml`, `shellcheck.yml`, and `prepare_env.yml` to check out the `embedded-workflows` repository and call the new script. - Adding authentication steps for Google Artifact Registry (GAR) using Workload Identity Federation, removing the dependency on PATs for Docker operations. - Overhauling the `release_docker_img.yml` workflow to use modern Docker actions (`docker/metadata-action`, `docker/build-push-action`) for building and pushing images to GAR. - Introducing a new reusable workflow `docker_build.yml` for standardized Docker image builds. - Adding the centralized `build_for_ultimaker.sh` script.
This commit standardizes the checkout process for the `embedded-workflows` repository across all reusable workflows. - An `embedded_workflows_branch` input is added to the `release_pkg` workflow to align it with other workflows. - The default branch for checking out `embedded-workflows` is temporarily set to `EMB-115_migrate_to_gar` across all workflows to facilitate ongoing development. - The checkout step in `release_pkg` is cleaned up by removing an unnecessary PAT and fetch-depth. - A redundant "Security Best Practices" summary is removed from the `docker_build` workflow.
The `UMLM_ENCRYPTION_KEY` is now passed as a temporary environment variable directly to the `build_for_ultimaker.sh` script instead of being exported for the entire step. This improves security by limiting the scope of the secret. Additionally, `TODO` comments in the CI workflows have been standardized.
The static analysis Docker images (clang-tidy, clang-format, cppcheck) are hardened by creating and running as a non-privileged user. Additionally, the shellcheck script is updated to mount the source directory as read-only to prevent accidental modifications.
This reverts commit 8b8d996.
This commit removes the dependency on the `embedded-workflows` repository by deleting the centralized `build_for_ultimaker.sh` script and the `docker_build.yml` workflow. The CI workflows (`build.yml`, `release_pkg.yml`, `unit_test.yml`, `shellcheck.yml`, `prepare_env.yml`, and `release_docker_img.yml`) are updated to no longer check out the `embedded-workflows` repository. Instead, they now rely on local scripts and configurations. Key changes include: - Deleting `scripts/build_for_ultimaker.sh` and `.github/workflows/docker_build.yml`. - Updating workflow files to remove the checkout step for `embedded-workflows`. - Simplifying Docker authentication and build steps, removing logic related to Google Artifact Registry (GAR) in favor of direct Docker commands and GitHub Container Registry (`ghcr.io`) login where needed. - Adjusting build, test, and shellcheck jobs to call local scripts directly. - Cleaning up unused inputs and environment variables from the workflows.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
EMB-115 Migrate to Google Artifact Registry (GAR) with Workload Identity Federation and SemVer 2.0
📋 Summary
This PR modernizes the embedded firmware CI/CD infrastructure by migrating from Cloudsmith to Google Artifact Registry (GAR). Key highlights include the implementation of Workload Identity Federation (WIF) for secure, credential-free GCP authentication and a comprehensive Semantic Versioning 2.0 strategy.
📦 Semantic Versioning 2.0 Strategy
Version generation is now fully automated. The format follows the standard SemVer 2.0 structure:
📊 SemVer Workflow Diagram
This diagram illustrates how GitHub events trigger specific versioning and repository logic:
graph TB Start([GitHub Event]) --> EventType{Event Type?} EventType -->|Push to Branch| BranchType{Is Master Branch?} EventType -->|Push Tag| TagPush[Tag Push Event] EventType -->|Pull Request| PREvent[Pull Request Event] %% Master Branch Flow BranchType -->|Yes: main/master/stable| MasterFlow[Master Branch Merge] MasterFlow --> GetLatestTag1[Get Latest Tag via git describe] GetLatestTag1 --> BumpPatch1[Bump Patch Version] BumpPatch1 --> NightlyFormat[Format: X.Y.Z-alpha.0+YYYYMMDD.branch.sha] NightlyFormat --> NightlyRepo[Repository: nightly-builds] %% Regular Branch Flow BranchType -->|No: feature/bugfix| RegularBranch[Regular Branch Commit] RegularBranch --> GetLatestTag2[Get Latest Tag via git describe] GetLatestTag2 --> BumpPatch2[Bump Patch Version] BumpPatch2 --> AlphaFormat[Format: X.Y.Z-alpha.0+sha] AlphaFormat --> DevRepo1[Repository: packages-dev] %% Pull Request Flow PREvent --> GetLatestTag3[Get Latest Tag via git describe] GetLatestTag3 --> BumpPatch3[Bump Patch Version] BumpPatch3 --> PRFormat[Format: X.Y.Z-alpha.0+sha] PRFormat --> DevRepo2[Repository: packages-dev] %% Tag Flow TagPush --> ParseTag{Parse Tag} ParseTag -->|Valid SemVer Tag| CheckPreRelease{Contains Prerelease?} ParseTag -->|Invalid Format| FallbackVersion[Fallback to Auto-Generated] FallbackVersion --> GetLatestTag4[Get Latest Tag] GetLatestTag4 --> BumpPatch4[Bump Patch Version] BumpPatch4 --> DevRepo3[Repository: packages-dev] %% Tag with Prerelease CheckPreRelease -->|Yes: alpha/beta/rc| PreReleaseTag[X.Y.Z-prerelease.N] PreReleaseTag --> DevRepo4[Repository: packages-dev] %% Production Release CheckPreRelease -->|No: Production| ProductionTag[X.Y.Z] ProductionTag --> ProdRepo[Repository: packages-released] %% Styling classDef masterStyle fill:#4CAF50,stroke:#2E7D32,stroke-width:3px,color:#fff classDef devStyle fill:#2196F3,stroke:#1565C0,stroke-width:3px,color:#fff classDef prodStyle fill:#F44336,stroke:#C62828,stroke-width:3px,color:#fff classDef processStyle fill:#FF9800,stroke:#E65100,stroke-width:2px,color:#fff class NightlyRepo masterStyle class DevRepo1,DevRepo2,DevRepo3,DevRepo4 devStyle class ProdRepo prodStyle class MasterFlow,RegularBranch,PREvent,TagPush processStyle🏗️ Version Format Breakdown
The version components provide the following information:
graph LR Version[1.2.3-beta.1+20260118.main.abc1234] Version --> Major[Major: 1] Version --> Minor[Minor: 2] Version --> Patch[Patch: 3] Version --> PreRelease[Prerelease: beta.1] Version --> BuildMeta[Build Metadata: 20260118.main.abc1234] Major --> MajorDesc[Breaking Changes<br/>Incompatible API] Minor --> MinorDesc[New Features<br/>Backward Compatible] Patch --> PatchDesc[Bug Fixes<br/>Backward Compatible] PreRelease --> PreDesc[Not Stable<br/>alpha → beta → rc] BuildMeta --> MetaDesc[Traceability<br/>Date, Branch, SHA] classDef componentStyle fill:#9C27B0,stroke:#6A1B9A,stroke-width:2px,color:#fff classDef descStyle fill:#E1BEE7,stroke:#9C27B0,stroke-width:1px,color:#333 class Major,Minor,Patch,PreRelease,BuildMeta componentStyle class MajorDesc,MinorDesc,PatchDesc,PreDesc,MetaDesc descStyle📦 Repository Distribution Strategy
Packages are automatically routed to the correct repository based on their maturity:
graph TB Commit([Code Commit/Tag]) --> Decision{What is it?} Decision -->|Master Merge| Nightly[Nightly Build] Decision -->|Alpha Tag| AlphaTag[Alpha Release] Decision -->|Beta Tag| BetaTag[Beta Release] Decision -->|RC Tag| RCTag[RC Release] Decision -->|Release Tag| ReleaseTag[Production Release] Decision -->|Other Commit| DevCommit[Development Commit] Nightly --> NightlyRepo[(nightly-builds<br/>X.Y.Z-alpha.0+YYYYMMDD.branch.sha)] AlphaTag --> DevRepo1[(packages-dev<br/>X.Y.Z-alpha.N)] BetaTag --> DevRepo2[(packages-dev<br/>X.Y.Z-beta.N)] RCTag --> DevRepo3[(packages-dev<br/>X.Y.Z-rc.N)] DevCommit --> DevRepo4[(packages-dev<br/>X.Y.Z-alpha.0+sha)] ReleaseTag --> ProdRepo[(packages-released<br/>X.Y.Z)] NightlyRepo --> NightlyUse[Daily Testing<br/>Continuous Integration] DevRepo1 --> DevUse1[Internal Testing] DevRepo2 --> DevUse2[QA Testing] DevRepo3 --> DevUse3[Pre-Production Validation] DevRepo4 --> DevUse4[Development Testing] ProdRepo --> ProdUse[Production Deployment<br/>Customer Releases] classDef nightlyStyle fill:#673AB7,stroke:#4527A0,stroke-width:3px,color:#fff classDef devStyle fill:#2196F3,stroke:#1565C0,stroke-width:3px,color:#fff classDef prodStyle fill:#4CAF50,stroke:#2E7D32,stroke-width:3px,color:#fff class NightlyRepo nightlyStyle class DevRepo1,DevRepo2,DevRepo3,DevRepo4 devStyle class ProdRepo prodStyle1. Automatic Patch Bumping
To prevent version conflicts and remove manual overhead, patch versions are automatically incremented from the latest reachable tag.
graph LR A[Latest Tag: v1.2.3] --> B[Auto Bump Patch] B --> C[Next Version: 1.2.4] C --> D[Add Prerelease: 1.2.4-alpha.0] D --> E[Add Build Meta: +sha] E --> F[Final: 1.2.4-alpha.0+abc1234] style A fill:#FFE0B2,stroke:#E65100,stroke-width:2px style F fill:#C8E6C9,stroke:#2E7D32,stroke-width:2pxWhy auto-bump?
🔐 Security & Authentication
Workload Identity Federation (WIF)
The primary security improvement is the transition to Workload Identity Federation. This removes the need for long-lived Service Account keys in GitHub Secrets.
Warning
A GitHub PAT is currently retained only for checkouts involving recursive sub-modules. This will be phased once a GitHub App has been setup for generating short-lived tokens.
🚀 Platform Team: Setup Steps
Note
Developers: You do not need to perform these steps. This infrastructure is managed by the Platform/DevOps team aka @Ultichiel or @jellespijker .
🚀 Setup Steps
Step 1: Create Workload Identity Pool (5 min)
Save this output: Full pool resource name
Step 2: Create Workload Identity Provider (5 min)
Save this output: Full provider resource name
Format:
projects/893160625502/locations/global/workloadIdentityPools/github-pool/providers/github-providerStep 3: Create Service Accounts (5 min)
Save these emails:
docker-ci@dev-embedded.iam.gserviceaccount.comapt-ci@dev-embedded.iam.gserviceaccount.comStep 4: Create GAR Repositories (10 min)
Step 5: Grant IAM Permissions (5 min)
Step 6: Bind Workload Identity - PER REPOSITORY (2 min each)
This must be done for EACH repository that will use the workflows.
Replace:
REPO_NAMEwith repository name (e.g.,opinicus,um-kernel)Repositories to bind:
Step 7: Configure GitHub Organization Variables (5 min)
Important
I'm currently using the WIF and GAR in the neoprep-staging GCP
"New organization variable" for each:
EMB_DOCKER_REGISTRYeurope-west1-docker.pkg.devEMB_GCP_PROJECTdev-embeddedEMB_GCP_LOCATIONeurope-west1EMB_DOCKER_REPOSITORYfirmware-imagesEMB_WI_PROVIDERprojects/893160625502/locations/global/workloadIdentityPools/github-pool/providers/github-providerEMB_DOCKER_SERVICE_ACCOUNTdocker-ci@dev-embedded.iam.gserviceaccount.comEMB_APT_SERVICE_ACCOUNTapt-ci@dev-embedded.iam.gserviceaccount.comImportant: Set as organization variables, not repository variables, so all repos can access them.
Step 8: Enable Required APIs (2 min)
gcloud services enable \ artifactregistry.googleapis.com \ iamcredentials.googleapis.com \ cloudresourcemanager.googleapis.com \ sts.googleapis.com✅ Verification
Verify Workload Identity Pool
Verify Provider
Verify Service Accounts
Verify GAR Repositories
Verify Docker Permissions
gcloud artifacts repositories get-iam-policy firmware-images \ --location=europe-west1 | grep docker-ciVerify APT Permissions
gcloud artifacts repositories get-iam-policy packages-released \ --location=europe-west1 | grep apt-ciVerify Workload Identity Binding (per repository)
💻 How to install packages locally or on a printer
Developers can pull Debian packages directly from GAR for local testing or printer installation.
1. Authenticate your machine
Ensure you have the Google Cloud CLI installed and are logged in:
2. Configure the APT Helper
GAR requires an authentication helper to allow
aptto communicate with Google's registries.sudo apt install apt-transport-artifact-registrypackages-dev):3. Install packages
Standard APT workflows now apply:
✅ Verification Checklist
vX.Y.Zand pre-release tags.opinicus.