Skip to content

CI/CD Pipeline

24.1. CircleCI Configuration

24.1.1. .circleci/config.yml Full Example

yaml
version: 2.1

orbs:
  node: circleci/node@6.3
  maven: circleci/maven@1.4

executors:
  java-executor:
    docker:
      - image: cimg/openjdk:21.0
    working_directory: ~/project/backend

  node-executor:
    docker:
      - image: cimg/node:22.0
    working_directory: ~/project/frontend

jobs:
  # ===== Backend =====
  backend-lint:
    executor: java-executor
    steps:
      - checkout:
          path: ~/project
      - restore_cache:
          keys:
            - maven-{{ checksum "pom.xml" }}
      - run:
          name: Format Verification
          command: mvn spotless:check
      - save_cache:
          key: maven-{{ checksum "pom.xml" }}
          paths:
            - ~/.m2

  backend-test:
    executor: java-executor
    steps:
      - checkout:
          path: ~/project
      - restore_cache:
          keys:
            - maven-{{ checksum "pom.xml" }}
      - run:
          name: Run Tests
          command: mvn test
      - run:
          name: Coverage Report
          command: mvn jacoco:report
      - store_test_results:
          path: target/surefire-reports
      - store_artifacts:
          path: target/site/jacoco

  backend-build:
    executor: java-executor
    steps:
      - checkout:
          path: ~/project
      - restore_cache:
          keys:
            - maven-{{ checksum "pom.xml" }}
      - run:
          name: Build
          command: mvn package -DskipTests
      - persist_to_workspace:
          root: ~/project
          paths:
            - backend/target/*.jar

  backend-security-scan:
    executor: java-executor
    steps:
      - checkout:
          path: ~/project
      - restore_cache:
          keys:
            - maven-{{ checksum "pom.xml" }}
      - run:
          name: OWASP Dependency Scan
          command: mvn dependency-check:check
      - store_artifacts:
          path: target/dependency-check-report.html

  # ===== Frontend =====
  frontend-lint:
    executor: node-executor
    steps:
      - checkout:
          path: ~/project
      - run:
          name: Install Dependencies
          command: yarn install --frozen-lockfile
      - run:
          name: ESLint Verification
          command: yarn lint
      - run:
          name: Prettier Verification
          command: yarn format:check

  frontend-build:
    executor: node-executor
    steps:
      - checkout:
          path: ~/project
      - run:
          name: Install Dependencies
          command: yarn install --frozen-lockfile
      - run:
          name: Type Check
          command: yarn type-check
      - run:
          name: Build
          command: yarn build
      - persist_to_workspace:
          root: ~/project
          paths:
            - frontend/dist

  # ===== Deployment =====
  deploy:
    docker:
      - image: cimg/base:current
    steps:
      - attach_workspace:
          at: ~/project
      - run:
          name: Deploy
          command: echo "Execute deployment script"

workflows:
  build-and-deploy:
    jobs:
      # Lint (parallel)
      - backend-lint
      - frontend-lint

      # Test (after lint passes)
      - backend-test:
          requires:
            - backend-lint

      # Build (after lint passes, parallel)
      - backend-build:
          requires:
            - backend-test
      - frontend-build:
          requires:
            - frontend-lint

      # Security scan (weekly or manual)
      - backend-security-scan:
          requires:
            - backend-lint
          filters:
            branches:
              only: main

      # Deploy (main branch only)
      - deploy:
          requires:
            - backend-build
            - frontend-build
          filters:
            branches:
              only: main

24.2. Pipeline Stages

24.2.1. Execution Flow

┌─────────────────────────────────────────────────┐
│                   Push / PR                      │
└──────────────────────┬──────────────────────────┘

           ┌───────────┴───────────┐
           ▼                       ▼
    backend-lint            frontend-lint
           │                       │
           ▼                       │
    backend-test                   │
           │                       │
           ▼                       ▼
    backend-build           frontend-build
           │                       │
           └───────────┬───────────┘


                    deploy
                  (main only)

24.2.2. Stage Responsibilities

StageResponsibilityOn Failure
LintCode format and ESLint rule verificationPR merge blocked
TestUnit/integration test execution, coverage measurementPR merge blocked
BuildCompilation, bundlingPR merge blocked
Security ScanDependency vulnerability inspectionWarning report generated
DeployBuild artifact deploymentRollback procedure initiated

24.3. Environment-Specific Deployment Strategy

24.3.1. Deployment Conditions

EnvironmentTriggerAuto/Manual
devOn merge to mainAutomatic
stagingMerge to main + manual approvalManual
productionOn release tag (v*) creationAutomatic after manual approval

24.3.2. Rollback Procedure

The following procedure must be followed when issues arise after a production deployment.

  1. Identify the issue and assess the impact scope
  2. Redeploy using the previous version tag
  3. Create a hotfix branch and apply the fix
  4. Emergency PR review -> merge -> redeploy

24.3.3. Required Scripts

The frontend package.json must include the following scripts.

json
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "type-check": "vue-tsc --noEmit"
  }
}

TIENIPIA QUALIFIED STANDARD