Aller au contenu principal

AWS CodeBuild


1 - Présentation

AWS CodeBuild est un service de build entièrement managé qui compile le code source, exécute les tests et produit des artefacts prêts au déploiement.


2 - Configuration d'un projet

2.1 Créer un projet CodeBuild

# Via CLI
aws codebuild create-project \
--name mon-projet-build \
--source type=CODECOMMIT,location=https://git-codecommit.eu-west-1.amazonaws.com/v1/repos/mon-app \
--artifacts type=S3,location=mon-bucket-artifacts \
--environment type=LINUX_CONTAINER,image=aws/codebuild/amazonlinux2-x86_64-standard:4.0,computeType=BUILD_GENERAL1_SMALL \
--service-role arn:aws:iam::123456789:role/CodeBuildServiceRole

2.2 Via CloudFormation

AWSTemplateFormatVersion: '2010-09-09'
Description: CodeBuild Project

Resources:
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: mon-projet-build
Description: Build de mon application
ServiceRole: !GetAtt CodeBuildRole.Arn

Source:
Type: CODECOMMIT
Location: !Sub https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/mon-app
BuildSpec: buildspec.yml

Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0
PrivilegedMode: true # Pour Docker
EnvironmentVariables:
- Name: ENV
Value: production
- Name: SECRET_KEY
Type: SECRETS_MANAGER
Value: my-secret:key

Artifacts:
Type: S3
Location: !Ref ArtifactsBucket
Name: build-output
Packaging: ZIP

Cache:
Type: S3
Location: !Sub ${CacheBucket}/cache

LogsConfig:
CloudWatchLogs:
Status: ENABLED
GroupName: /codebuild/mon-projet

TimeoutInMinutes: 30
QueuedTimeoutInMinutes: 60

Tags:
- Key: Project
Value: MonProjet

CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser
Policies:
- PolicyName: CodeBuildPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
Resource: !Sub ${ArtifactsBucket.Arn}/*
- Effect: Allow
Action:
- codecommit:GitPull
Resource: '*'

3 - buildspec.yml

3.1 Structure de base

# buildspec.yml
version: 0.2

env:
variables:
JAVA_HOME: "/usr/lib/jvm/java-17-amazon-corretto"
parameter-store:
DB_PASSWORD: /myapp/db/password
secrets-manager:
API_KEY: my-secret:api_key

phases:
install:
runtime-versions:
nodejs: 18
docker: 20
commands:
- echo "Installing dependencies..."
- npm ci

pre_build:
commands:
- echo "Running pre-build..."
- npm run lint
- aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REPO

build:
commands:
- echo "Building..."
- npm run build
- docker build -t $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION .
- docker push $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION

post_build:
commands:
- echo "Build completed on $(date)"
- echo "Creating imagedefinitions.json"
- printf '[{"name":"app","imageUri":"%s"}]' $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION > imagedefinitions.json

artifacts:
files:
- dist/**/*
- imagedefinitions.json
discard-paths: no
base-directory: .

cache:
paths:
- node_modules/**/*
- /root/.npm/**/*

reports:
jest-reports:
files:
- 'junit.xml'
base-directory: coverage
file-format: JUNITXML
coverage-reports:
files:
- 'coverage/clover.xml'
file-format: CLOVERXML

3.2 Variables d'environnement prédéfinies

VariableDescription
CODEBUILD_BUILD_IDID unique du build
CODEBUILD_BUILD_NUMBERNuméro séquentiel du build
CODEBUILD_RESOLVED_SOURCE_VERSIONCommit ID
CODEBUILD_SOURCE_REPO_URLURL du repo source
CODEBUILD_WEBHOOK_HEAD_REFBranche pour les webhooks
CODEBUILD_SRC_DIRRépertoire des sources

3.3 Build Docker complet

version: 0.2

env:
variables:
AWS_REGION: eu-west-1
ECR_REPO: 123456789.dkr.ecr.eu-west-1.amazonaws.com/mon-app

phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_REPO
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}

build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $ECR_REPO:latest .
- docker tag $ECR_REPO:latest $ECR_REPO:$IMAGE_TAG

post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker images...
- docker push $ECR_REPO:latest
- docker push $ECR_REPO:$IMAGE_TAG
- echo Writing image definitions file...
- printf '[{"name":"container","imageUri":"%s"}]' $ECR_REPO:$IMAGE_TAG > imagedefinitions.json

artifacts:
files:
- imagedefinitions.json

4 - Environnements de build

4.1 Images managées

ImageDescription
aws/codebuild/amazonlinux2-x86_64-standard:4.0Amazon Linux 2, multi-runtime
aws/codebuild/amazonlinux2-x86_64-standard:5.0Amazon Linux 2023
aws/codebuild/standard:7.0Ubuntu, multi-runtime

4.2 Compute types

TypevCPUMémoirePrix/min
BUILD_GENERAL1_SMALL33 GB$0.005
BUILD_GENERAL1_MEDIUM715 GB$0.01
BUILD_GENERAL1_LARGE1572 GB$0.02
BUILD_GENERAL1_2XLARGE72145 GB$0.20

4.3 Image Docker personnalisée

# Dockerfile pour environnement de build custom
FROM aws/codebuild/amazonlinux2-x86_64-standard:4.0

# Installer des outils supplémentaires
RUN yum install -y \
terraform \
ansible \
&& yum clean all

# Configurer des outils
COPY scripts/setup.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/setup.sh

5 - Test Reports

5.1 Configuration des rapports

# buildspec.yml
reports:
# Rapports de tests unitaires
unit-tests:
files:
- '**/*'
base-directory: test-results/unit
file-format: JUNITXML

# Couverture de code
coverage:
files:
- 'coverage/cobertura-coverage.xml'
file-format: COBERTURAXML

# Tests Cucumber
cucumber:
files:
- 'reports/cucumber.json'
file-format: CUCUMBERJSON

5.2 Générer des rapports

# Jest avec rapport JUnit
npm test -- --coverage --reporters=default --reporters=jest-junit

# pytest avec rapport JUnit
pytest --junitxml=test-results/pytest.xml

# Go tests
go test -v ./... 2>&1 | go-junit-report > test-results/report.xml

6 - Cache et optimisation

6.1 Cache S3

cache:
paths:
- 'node_modules/**/*'
- '/root/.m2/**/*'
- '/root/.gradle/**/*'
- '/root/.cache/pip/**/*'

6.2 Cache local

cache:
type: LOCAL
modes:
- LOCAL_SOURCE_CACHE # Cache du code source
- LOCAL_DOCKER_LAYER_CACHE # Cache des layers Docker
- LOCAL_CUSTOM_CACHE # Cache personnalisé

6.3 Optimisation Docker

# Multi-stage build pour réduire la taille
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

7 - Webhooks et déclencheurs

7.1 Webhook GitHub

# Créer un webhook
aws codebuild create-webhook \
--project-name mon-projet \
--filter-groups '[
[
{"type": "EVENT", "pattern": "PUSH"},
{"type": "HEAD_REF", "pattern": "^refs/heads/main$"}
],
[
{"type": "EVENT", "pattern": "PULL_REQUEST_MERGED"}
]
]'

7.2 Build badges

<!-- README.md -->
![Build Status](https://codebuild.eu-west-1.amazonaws.com/badges?uuid=abc123&branch=main)

Résumé

Dans ce chapitre, nous avons appris :

  • La création et configuration de projets CodeBuild
  • L'écriture du fichier buildspec.yml
  • Les environnements et types de compute
  • Les test reports et couverture
  • Le cache et l'optimisation
  • Les webhooks et déclencheurs

Prochaine étape

Dans le prochain chapitre, nous verrons AWS CodeDeploy pour automatiser les déploiements.

→ Chapitre suivant : AWS CodeDeploy


← Retour à la table des matières