# Define pipeline inputs for runtime configuration spec: inputs: gpg_passphrase: description: "Passphrase for GPG signing key" type: string default: "" --- stages: - configure - build - test - package - encrypt - publish # Set variables used for builds in CI, should probably set this in the build container if possible variables: AF_PATH: /usr/local # Use Docker-outside-of-Docker (DooD) by mounting the host's Docker socket DOCKER_HOST: unix:///var/run/docker.sock # Disable TLS as we're using the local socket DOCKER_TLS_CERTDIR: "" DOCKER_AUTH_CONFIG: '{"auths":{"gl.whitefoxdefense.com:5050":{"auth":"Z2l0bGFiK2RlcGxveS10b2tlbi04OmdsZHQtSnNiVFFoeXhpUWNxcHFXMndfYjY="}}}' LD_LIBRARY_PATH: /usr/local/lib # Experimental for the EKS runner # DOCKER_HOST: "tcp://docker:2375" # Dynamically pull the build container image name from the devcontainer.json file. # This acts as a single-source-of-truth to keep local and CI builds unified. configure: stage: configure image: alpine:latest script: - BUILD_IMAGE=$(grep '"image":' .devcontainer/devcontainer.json | cut -d '"' -f 4) - printf 'BUILD_IMAGE=%s' "$BUILD_IMAGE" > build_image.env - ls -la build_image.env - cat build_image.env artifacts: reports: dotenv: build_image.env tags: - test-ci-cd # Build the Rust application using Nix build: stage: build image: nixos/nix:latest before_script: # Enable flakes and nix-command - mkdir -p ~/.config/nix - echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf script: # Generate Cargo.lock if it doesn't exist - nix develop --command cargo generate-lockfile || true # Build the Rust application - nix build .#app # Copy the result for artifacts - mkdir -p build-output - cp -rL result/* build-output/ || cp result build-output/hello-world artifacts: paths: - build-output/ - Cargo.lock expire_in: 1 hour tags: - test-ci-cd # Test the application test: stage: test image: nixos/nix:latest before_script: - mkdir -p ~/.config/nix - echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf script: # Run the application in a Nix shell with all dependencies - nix develop --command cargo test # You could also run the binary here if needed # - nix run .#app dependencies: - build tags: - test-ci-cd # Build Docker image using Nix and load it into Docker (DooD pattern) package-docker-image-with-nix: stage: package image: nixos/nix:latest before_script: # Install Docker CLI in the Nix container - nix-env -iA nixpkgs.docker # Enable flakes - mkdir -p ~/.config/nix - echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf script: # Build the Docker image using Nix - nix build .#docker # Load the image into Docker daemon (running on host via socket) - docker load < result # Tag the image - docker tag hello-world:latest hello-world:${CI_COMMIT_SHORT_SHA} # Test run the container - docker run --rm hello-world:latest # Optional: Push to registry if configured # - docker tag hello-world:latest ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA} # - docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA} dependencies: - build tags: - test-ci-cd # This job requires a GitLab runner with Docker socket access # The runner should have /var/run/docker.sock mounted # Alternative: Build using Docker directly (DooD) package-docker-image: stage: package image: docker:latest services: [] # No dind service variables: DOCKER_HOST: unix:///var/run/docker.sock before_script: # Verify Docker access - docker info script: - docker build -t hello-world:traditional-${CI_COMMIT_SHORT_SHA} . - docker run --rm hello-world:traditional-${CI_COMMIT_SHORT_SHA} - docker save -o hello-world.tar.gz hello-world:traditional-${CI_COMMIT_SHORT_SHA} dependencies: - build tags: - test-ci-cd only: - branches artifacts: expire_in: 1 week name: wf-image-dood-$BUILD_VARIANT-$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA paths: - ./hello-world.tar.gz encrypt: stage: encrypt image: alpine:latest needs: - job: package-docker-image artifacts: true before_script: - apk add --no-cache gnupg script: - | if [ -n "$GPG_PRIVATE_KEY" ]; then gpg --batch --import "$GPG_PRIVATE_KEY" else echo "Warning: GPG_PRIVATE_KEY not set. Using existing keyring." fi - echo "$GPG_PUBLIC_KEY" | gpg --import - | echo 'DD0007338E2C43BD553D569377D9D93F96483723:6:' | gpg --import-ownertrust - echo "Encrypting hello-world.tar.gz..." - printf '%s' '$[[ inputs.gpg_passphrase ]]' > passphrase.txt - | gpg --batch --yes \ --pinentry-mode loopback \ --passphrase-file passphrase.txt \ --sign --default-key B35BF119FC3AE04C \ --encrypt -r 6C4C078A1C72925E \ -o hello-world.tar.gz.gpg \ hello-world.tar.gz - | if [ -f "hello-world.tar.gz.gpg" ]; then echo "Encryption successful!" ls -lh hello-world.tar.gz.gpg else echo "Error: Encrypted file not created" exit 1 fi artifacts: expire_in: 1 week name: encrypted-image-$CI_COMMIT_SHORT_SHA paths: - hello-world.tar.gz.gpg tags: - test-ci-cd publish_gpg: stage: publish image: curlimages/curl:8.5.0 # If any build variant fails, this job will not publish any artifacts. needs: - job: encrypt artifacts: true script: # Version scheme: CI-only versions are easy to identify + clean up later - PKG_NAME="hello-world.tar.gz.gpg" - FILE="./hello-world.tar.gz.gpg" - PKG_VERSION="${CI_COMMIT_SHORT_SHA}-${CI_PIPELINE_IID}" - echo "Uploading ${FILE} as ${PKG_NAME} ${PKG_VERSION}" - | curl --fail \ --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \ --upload-file "${FILE}" \ "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${PKG_NAME}/${PKG_VERSION}/$(basename "${FILE}")"