Main branches
- Main: This branch contains the production-ready code. All releases are tagged here.
- Develop: This branch serves as an integration branch for features. It contains the latest delivered development changes for the next release.
Supporting Branches
- Feature Branches: Created from the
develop
branch, these branches are used todevelop
new features. Once a feature is complete, it is merged back intodevelop
. - Release Branches: Created from the
develop
branch when a set of features is ready for a release. This branch allows for final testing and bug fixing before merging intomain
anddevelop
. - Hotfix Branches: Created from the
main
branch to quickly address critical issues in production. Once fixed, changes are merged back into bothmain
anddevelop
.
Workflow
- Initialization: Start by creating the
develop
branch frommain
. - Feature Development: Developers create feature branches from
develop
, work on their features, and merge them back intodevelop
when done. - Release Preparation: When ready for a release, create a release branch from
develop
, perform final testing and fixes, then merge into bothmain
anddevelop
. - Hotfixes: For urgent fixes, create a hotfix branch from
main
, apply the fix, and merge back into bothmain
anddevelop
.
Key concepts
- Workflow: A workflow is a configurable automated process that consists of one or more jobs.
- Events: Events are specific activities in a repository that trigger workflows.
- Step: Steps are individual tasks within a job. They can run commands or actions (reusable extensions).
- Actions: Actions are reusable units of code that perform specific tasks. They can be used within steps to simplify workflows.
- Jobs: A job is a set of steps that run as part of your workflow. Recall that a step can run a task, a command, or an action.
- Runner: A runner is a machine, either hosted by GitHub or self-hosted, that executes the jobs in a workflow.
Managing Secrets
Manage:
- Go to your repository on GitHub.
- Click on the Settings tab.
- In the left sidebar, click on Secrets and variables > Actions.
- Click on New repository secret.
- Add a name for your secret and its value, then click Add secret.
Use:
To use a secret in your workflow, reference it in your YAML file like this:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Use secret
run: echo ${{ secrets.MY_SECRET }}
Note: Always use secrets for sensitive information like API keys, tokens, and passwords.
Managing Environment Variables
Environment-Specific Variables: Navigate to Settings > Environments, create an environment. Environment Variables in Workflow: You can define environment variables directly in your workflow file.
jobs:
build:
runs-on: ubuntu-latest
env:
MY_VARIABLE: 'value'
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Use environment variable
run: echo $MY_VARIABLE
Caching
Caching in GitHub Actions is a mechanism that allows you to store and reuse files or data between workflow runs.
- Cache Creation: During a workflow run, you can create a cache by specifying a unique key. This key is used to identify the cache.
- Cache Storage: The cache is stored on GitHub’s servers.
- Cache Restoration: In subsequent workflow runs, the cache can be restored using the same key, allowing you to reuse the stored data.
name: Java CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
- name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
The actions/cache@v3 action caches the Maven dependencies located in the ~/.m2/repository directory.
Matrix builds
Parallel Jobs
You can define multiple jobs within the jobs section of your workflow YAML file.
name: Parallel Jobs Example
on: [push]
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests
run: echo "Running tests for job1"
job2:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build project
run: echo "Building project for job2"
Security for CI/CD pipeline
- Store sensitive information like API keys, tokens, and passwords in GitHub Secrets.
- Integrate security tools like CodeQL, Snyk, or Gitleaks to automatically scan your code for vulnerabilities.
Setup ECS & ECR
- Create an ECR Repository
- Create an ECS Cluster
- Dockerize Java Application (Create a Dockerfile)
- Create access key from user. (there are several ways to get credentails from AWS)
- Create ECS Task Definition (Task definition sample file)
- Finally, we create github actions workflow.
FROM openjdk:17-jdk-alpine
COPY target/sample-service*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
This file will define how to build your Docker image.
Setup CI/CD
name: Java CI with SonarQube
on:
push:
branches:
- lite_version
- ecs_version
jobs:
build:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get commit message
id: get_commit_message
run: echo "::set-output name=message::$(git log -1 --pretty=%B)"
- name: Check commit message
if: contains(steps.get_commit_message.outputs.message, 'Build CI')
run: echo "Commit message contains the trigger phrase!"
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Maven packages
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Run tests and generate JaCoCo report
run: mvn test jacoco:report
- name: Publish JaCoCo report
uses: actions/upload-artifact@v4
with:
name: jacoco-report
path: target/site/jacoco
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@master
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
with:
mask-password: 'true'
- name: Build, tag, and push image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ vars.ECR_REPOSITORY }}
IMAGE_TAG: latest
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: my-java-app
image: ${{ steps.ecr-login.outputs.registry }}/my-java-app:latest
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: my-java-app-service
cluster: my-cluster
wait-for-service-stability: true