Skip to content

GitLab Build Pipeline | Complete CI/CD Build Guide

GitLab CI/CD build pipelines are essential for automating the compilation, testing, and packaging of your applications. This guide covers building various types of applications and managing artifacts effectively.

Building Angular applications in GitLab CI/CD requires Node.js and npm. Here’s a comprehensive build configuration:

.gitlab-ci.yml
stages:
- build
- test
- package
variables:
NODE_VERSION: "18"
ANGULAR_CLI_VERSION: "16"
build_angular:
stage: build
image: node:${NODE_VERSION}
before_script:
- npm install -g @angular/cli@${ANGULAR_CLI_VERSION}
- npm ci --cache .npm --prefer-offline
script:
- ng build --configuration=production
- ng test --watch=false --browsers=ChromeHeadless
artifacts:
paths:
- dist/
expire_in: 1 hour
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .npm/

Advanced Angular Build with Multiple Environments

Section titled “Advanced Angular Build with Multiple Environments”
build_angular_dev:
stage: build
image: node:18
script:
- npm ci
- ng build --configuration=development
artifacts:
paths:
- dist/
expire_in: 30 mins
only:
- develop
build_angular_prod:
stage: build
image: node:18
script:
- npm ci
- ng build --configuration=production --aot
- ng test --watch=false --code-coverage
artifacts:
paths:
- dist/
- coverage/
expire_in: 1 week
only:
- main

Building .NET Core applications requires the appropriate SDK and proper configuration for microservices architecture.

build_dotnet:
stage: build
image: mcr.microsoft.com/dotnet/sdk:8.0
before_script:
- dotnet --version
script:
- dotnet restore
- dotnet build --configuration Release --no-restore
- dotnet test --configuration Release --no-build --verbosity normal
artifacts:
paths:
- "*/bin/Release/"
- "*/obj/"
expire_in: 1 hour
variables:
DOTNET_VERSION: "8.0"
build_user_service:
stage: build
image: mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}
script:
- cd src/UserService
- dotnet restore
- dotnet build --configuration Release
- dotnet publish -c Release -o ../../publish/UserService
artifacts:
paths:
- publish/UserService/
expire_in: 1 hour
build_order_service:
stage: build
image: mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}
script:
- cd src/OrderService
- dotnet restore
- dotnet build --configuration Release
- dotnet publish -c Release -o ../../publish/OrderService
artifacts:
paths:
- publish/OrderService/
expire_in: 1 hour
build_api_gateway:
stage: build
image: mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}
script:
- cd src/ApiGateway
- dotnet restore
- dotnet build --configuration Release
- dotnet publish -c Release -o ../../publish/ApiGateway
artifacts:
paths:
- publish/ApiGateway/
expire_in: 1 hour
build_dotnet_docker:
stage: build
image: docker:20.10.16
services:
- docker:20.10.16-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
script:
- docker build -f Dockerfile.build -t myapp-build .
- docker create --name temp-container myapp-build
- docker cp temp-container:/app/publish ./publish
- docker rm temp-container
artifacts:
paths:
- publish/
expire_in: 1 hour

🗄️ Create Database Script Compatible with Liquibase

Section titled “🗄️ Create Database Script Compatible with Liquibase”

Liquibase integration requires proper changelog management and database script generation.

generate_liquibase_scripts:
stage: build
image: liquibase/liquibase:4.23
variables:
DB_URL: "jdbc:postgresql://localhost:5432/devdb"
DB_USERNAME: "dbuser"
DB_PASSWORD: "dbpass"
script:
# Generate changelog from existing database
- liquibase --url=${DB_URL} --username=${DB_USERNAME} --password=${DB_PASSWORD} generateChangeLog --changeLogFile=generated-changelog.xml
# Validate changelog
- liquibase --url=${DB_URL} --username=${DB_USERNAME} --password=${DB_PASSWORD} validate
# Generate SQL preview
- liquibase --url=${DB_URL} --username=${DB_USERNAME} --password=${DB_PASSWORD} updateSQL > update-preview.sql
artifacts:
paths:
- generated-changelog.xml
- update-preview.sql
- liquibase.properties
expire_in: 1 week
validate_database_schema:
stage: build
image: liquibase/liquibase:4.23
services:
- postgres:13
variables:
POSTGRES_DB: testdb
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
DB_URL: "jdbc:postgresql://postgres:5432/testdb"
script:
- echo "Waiting for PostgreSQL to be ready..."
- sleep 30
- liquibase --url=${DB_URL} --username=${POSTGRES_USER} --password=${POSTGRES_PASSWORD} update
- liquibase --url=${DB_URL} --username=${POSTGRES_USER} --password=${POSTGRES_PASSWORD} status
artifacts:
reports:
junit: liquibase-test-results.xml
build_database_scripts:
stage: build
image: liquibase/liquibase:4.23
parallel:
matrix:
- DATABASE: [postgresql, mysql, mssql]
script:
- |
case $DATABASE in
postgresql)
DB_URL="jdbc:postgresql://postgres:5432/testdb"
DB_DRIVER="org.postgresql.Driver"
;;
mysql)
DB_URL="jdbc:mysql://mysql:3306/testdb"
DB_DRIVER="com.mysql.cj.jdbc.Driver"
;;
mssql)
DB_URL="jdbc:sqlserver://mssql:1433;databaseName=testdb"
DB_DRIVER="com.microsoft.sqlserver.jdbc.SQLServerDriver"
;;
esac
- liquibase --url=${DB_URL} --driver=${DB_DRIVER} updateSQL > ${DATABASE}-update.sql
artifacts:
paths:
- "*.sql"
expire_in: 1 week

📦 Build Artifacts and Retention Policies

Section titled “📦 Build Artifacts and Retention Policies”

Proper artifact management is crucial for efficient CI/CD pipelines and storage optimization.

build_with_artifacts:
stage: build
script:
- echo "Building application..."
- mkdir -p build/
- echo "Application built successfully" > build/app.txt
artifacts:
paths:
- build/
expire_in: 1 week
when: always
reports:
junit: test-results.xml
coverage: coverage.xml
variables:
ARTIFACT_RETENTION_DAYS: "7"
build_production:
stage: build
script:
- make build-production
artifacts:
name: "production-build-${CI_COMMIT_SHORT_SHA}"
paths:
- dist/
- build/
expire_in: 30 days
when: on_success
only:
- main
build_development:
stage: build
script:
- make build-development
artifacts:
name: "dev-build-${CI_COMMIT_SHORT_SHA}"
paths:
- dist/
expire_in: ${ARTIFACT_RETENTION_DAYS} days
when: always
except:
- main
build_with_conditional_artifacts:
stage: build
script:
- make build
- make test
artifacts:
paths:
- dist/
- logs/
exclude:
- "**/*.tmp"
- "logs/debug.log"
expire_in: 1 week
when: on_failure
after_script:
- |
if [ "$CI_JOB_STATUS" = "failed" ]; then
echo "Build failed, collecting debug artifacts"
cp -r debug/ artifacts/debug/
fi
stages:
- build
- test
- package
build_app:
stage: build
script:
- make build
artifacts:
paths:
- build/
expire_in: 1 hour
test_app:
stage: test
dependencies:
- build_app
script:
- make test
artifacts:
paths:
- test-results/
expire_in: 1 day
package_app:
stage: package
dependencies:
- build_app
- test_app
script:
- make package
artifacts:
paths:
- packages/
expire_in: 1 month
build_parallel:
stage: build
parallel: 3
script:
- echo "Running parallel build job $CI_NODE_INDEX of $CI_NODE_TOTAL"
- make build-chunk-$CI_NODE_INDEX
artifacts:
paths:
- build-chunk-$CI_NODE_INDEX/
expire_in: 1 hour
build_with_cache:
stage: build
image: node:18
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
- .npm/
policy: pull-push
script:
- npm ci --cache .npm --prefer-offline
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
build_with_notifications:
stage: build
script:
- make build
after_script:
- |
if [ "$CI_JOB_STATUS" = "success" ]; then
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"Build succeeded for '"$CI_PROJECT_NAME"'"}' \
$SLACK_WEBHOOK_URL
fi
artifacts:
paths:
- build/
expire_in: 1 week

This comprehensive build pipeline guide covers the essential aspects of building Angular components, .NET Core microservices, database scripts, and managing artifacts effectively in GitLab CI/CD.