Skip to main content
In this section, we create a GitLab CI/CD pipeline that automatically builds Windows executables and submits them to CryptoHub for code signing. The pipeline uses a two-stage approach: compile the executable with MinGW in the build stage, then submit it for signing and poll for approval in the sign stage. This ensures signed artifacts are available for deployment without manual intervention.

Configure GitLab CI/CD variables

Store sensitive credentials and connection details as protected CI/CD variables:
1
Go to your GitLab project.
2
Select Settings > CI/CD.
3
Expand Variables.
4
Add the following variables:
Variable nameValue
PKI_P12_B64Base64-encoded PKCS#12 certificate
PKI_PASSPKCS#12 certificate password
To encode your PKCS#12 certificate as Base64:
Bash
Copy the contents of client-cert.p12.b64 into the PKI_P12_B64 variable. Why mask and protect: Protected variables are only exposed to protected branches (e.g., main). Masked variables are hidden in job logs. Both settings prevent credential exposure.

Create the pipeline configuration file

In your project root directory, create or edit .gitlab-ci.yml:
YAML

Configure project-wide timeout settings

The sign job can run for up to 3 days while waiting for approval. Increase the project-wide timeout:
Why this matters: GitLab’s default job timeout is 1 hour. Without this change, sign jobs will fail before approvers complete the workflow.
1
Go to Settings > CI/CD.
2
Expand General pipelines.
3
Set Timeout to 259200 seconds (3 days).
4
Select [ Save changes ].

Understand the pipeline structure

Stages:
  • build: Compiles the Windows executable using MinGW cross-compiler
  • sign: Submits the executable to CryptoHub, polls for approval, downloads the signed artifact
Job routing:
  • build_exe job uses the mingw tag, routing it to runners configured for MinGW builds
  • sign_exe job uses the codesign tag, routing it to runners with access to the Futurex registry
Artifact passing:
  • The build_exe job produces example.exe as an artifact
  • GitLab automatically makes this artifact available to the sign_exe job
  • The sign_exe job overwrites example.exe with the signed version and publishes it as a new artifact

Understand the build job configuration

YAML
Key elements:
  • image: Uses a public Docker image with MinGW cross-compiler pre-installed
  • tags: [mingw]: Routes this job to runners with the mingw tag
  • script: Compiles main.c into a Windows executable
  • artifacts: Preserves example.exe for the sign stage
Customization: Replace main.c with your actual source files. For multi-file projects, adjust the compilation command or use a Makefile.

Understand the sign job configuration

The sign job performs five operations:
  1. TLS setup: Decodes the PKCS #12 certificate and configures CryptoHub connection
  2. Request submission: Submits the executable for signing with a unique request name
  3. Status polling: Polls request status every 10 seconds until it reaches a terminal state (signed, denied, deleted)
  4. Signature download: Retrieves the signature for the executable when approval is complete. The Futurex CLI handles embedding the signature into the executable.
The GitLab service on the CryptoHub uses TLS authentication. This means authentication occurs automatically, immediately after the TLS negotiation, using the certificate itself rather than a username and password.
Configuration variables:
VariableDefaultPurpose
POLL_INTERVAL10Seconds between status checks
MAX_ATTEMPTS0Maximum polling attempts (0 = infinite)
CH_HOSTNAMEMust be defined. There is no default value.CryptoHub server hostname
CH_PORTMust be defined. There is no default value.CryptoHub server port
Polling behavior:
  • pending: Job sleeps for POLL_INTERVAL seconds and checks status again
  • signed: Job downloads the signature, and Futurex CLI embeds it in the executable.
  • denied: Job fails immediately with exit code 2
  • deleted/unknown: Job fails immediately with exit code 3 (request was removed from CryptoHub)
  • MAX_ATTEMPTS reached: Job fails with exit code 124 (timeout)
Exit codes:
Exit codeMeaningAction required
0Success (signature downloaded)None
2Request denied by approverReview denial reason in CryptoHub
3Request deleted or unknownCheck CryptoHub logs; request may have been manually removed
124Polling timeout reachedIncrease MAX_ATTEMPTS or resolve approval delays

Commit and test the pipeline

1
Commit .gitlab-ci.yml to your repository:
2
Go to your GitLab project and select CI/CD > Pipelines.
3
Verify the pipeline starts automatically.
4
Observe the build job complete within 1-2 minutes.
5
Monitor the sign job logs. The job will display status checks every 10 seconds:
6
Approve the signing request in CryptoHub.
7
Verify the sign job completes, downloads the signature, and embeds it into the artifact.

Result

You now have a working CI/CD pipeline that:
  • Automatically compiles Windows executables on every commit
  • Submits signature requests to CryptoHub
  • Polls for approval without manual intervention
  • Downloads signatures from CryptoHub once they are approved and uses the Futurex CLI to embed them in artifacts for deployment
The pipeline enforces administrator approval, ensuring no executable is signed without proper authorization.