본문 바로가기

카테고리 없음

[CI/CD] Github action for front

Intro.

 github repository를 dev와 prod로 나누어놓았다. 그래서 branch는 하나만 사용하고 repo로 환경을 분리한 구조로 세팅을 해보았다. 

 

1. github action in dev repo

(1) deploy.yaml

name: test-dev

on:
  workflow_dispatch:

jobs:
  build_deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_S3_REGION }}

      - name: Set Environment Variable
        run: |
          echo "HASH_TAG=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
        shell: bash

      - name: Cache node modules
        id: node-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          path: node_modules
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-

      - name: Install dependencies
        if: steps.node-cache.outputs.cache-hit != 'true'
        run: npm install --save --legacy-peer-deps

      - name: Dev build angular
        run: |
          npm run build:dev

      - name: Generate deployment dev package
        run: |
          mkdir -p deploy/dev/${{ env.HASH_TAG }}
          cp -r dist/work-caring-client/* deploy/dev/${{ env.HASH_TAG }}

      - name: Upload to S3 bucket env repo dev directory
        run: |
          aws s3 cp ./deploy/dev/ s3://${{ secrets.AWS_S3_BUCKET_ENV_REPO }}/dev --recursive

      - name: Upload to S3 bucket dev
        run: |
          aws s3 sync ./deploy/dev/${{ env.HASH_TAG }}/ s3://${{ secrets.AWS_S3_BUCKET_DEV }} --delete

      - name: Apply dev cloudfront invalidation generation
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${{ secrets.AWS_CLOUD_FRONT_ID_DEV }} \
            --path "/*"

      - name: Prod build angular
        run: |
          npm run build:prod

      - name: Generate deployment prod package
        run: |
          mkdir -p deploy/prod/${{ env.HASH_TAG }}
          cp -r dist/work-caring-client/* deploy/prod/${{ env.HASH_TAG }}

      - name: Upload to S3 bucket env repo prod directory
        run: |
          aws s3 cp ./deploy/prod/ s3://${{ secrets.AWS_S3_BUCKET_ENV_REPO }}/prod --recursive

 

 

1) checkout

      - name: Checkout
        uses: actions/checkout@v3

- git init을 하고 git branch를 배포할 브런치에 맞추는 작업을 진행한다.

 

2) setup node

      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'

- node를 set up하고 npm packages를 caching할 수 있는지 체크하는 단계이다. 

- cache할 수 있다면, Cache restored successfully 를 볼 수 있다.

 

3) configure-aws-credentials

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_S3_REGION }}

- aws에 접근할 수 있도록 자격증명을 하는 단계이다.

 

4) set global env variable

      - name: Set Environment Variable
        run: |
          echo "HASH_TAG=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
        shell: bash

- GitHUB_ENV 에 HASH_TAG 이름으로 hash값을 저장해 추가해놓는다.

 

5) caching

      - name: Cache node modules
        id: node-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          path: node_modules
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-

[1] 캐싱이 되었다면

- 위에서 캐싱 restore가 성공했으면 해당 작업에서 cache size를 확인하고 Cache restored successfully 을 리턴한다.

[2] 캐싱이 안 되었다면

- key : 캐시 복원 및 저장을 위한 키

- restore-keys  :  캐시 hit가 안 된다면, 캐시 복원에 사용될 키의 목록  

- cache-hit false return

 

6) install dependencies

      - name: Install dependencies
        if: steps.node-cache.outputs.cache-hit != 'true'
        run: npm install --save --legacy-peer-deps

- caching에 성공했다면, 해당 작업은 건너뛴다.

- caching에 성공하지 못했다면, 해당 명령어를 실행해 필요한 라이브러리들을 다운받는다.

 

7) apply them for dev

      - name: Dev build angular
        run: |
          npm run build:dev

      - name: Generate deployment dev package
        run: |
          mkdir -p deploy/dev/${{ env.HASH_TAG }}
          cp -r dist/work-caring-client/* deploy/dev/${{ env.HASH_TAG }}

      - name: Upload to S3 bucket env repo dev directory
        run: |
          aws s3 cp ./deploy/dev/ s3://${{ secrets.AWS_S3_BUCKET_ENV_REPO }}/dev --recursive

      - name: Upload to S3 bucket dev
        run: |
          aws s3 sync ./deploy/dev/${{ env.HASH_TAG }}/ s3://${{ secrets.AWS_S3_BUCKET_DEV }} --delete

      - name: Apply dev cloudfront invalidation generation
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${{ secrets.AWS_CLOUD_FRONT_ID_DEV }} \
            --path "/*"

[1] dev build를 실행한다.

[2] 해당 빌드된 파일을 deploy/dev/[hash] 경로에 복사한다.

[3] 복사된 빌드된 파일을 S3 버킷 env-repo/dev 디렉터리에 복사한다.

[4] 복사된 빌드된 파일을 S3 버킷 dev에 배포한다.

[5] cloudFront에 이전 버전이 적용된 캐싱을 삭제한다.

 

8) apply them for prod

      - name: Prod build angular
        run: |
          npm run build:prod

      - name: Generate deployment prod package
        run: |
          mkdir -p deploy/prod/${{ env.HASH_TAG }}
          cp -r dist/work-caring-client/* deploy/prod/${{ env.HASH_TAG }}

      - name: Upload to S3 bucket env repo prod directory
        run: |
          aws s3 cp ./deploy/prod/ s3://${{ secrets.AWS_S3_BUCKET_ENV_REPO }}/prod --recursive

[1] prod build를 실행한다.

[2] 해당 빌드된 파일을 deploy/prod/[hash] 경로에 복사한다.

[3] 복사된 빌드된 파일을 S3 버킷 env-repo/prod 디렉터리에 복사한다.

**여기에서 prod에 배포할 것이 아니므로 repo에만 static files를 저장해 놓는다.

 

(2) rollback.yaml

name: rollback

on:
  workflow_dispatch:
    inputs:
      hash-tag:
        description: 'git commit hash name'
        required: true
        type: string

jobs:
  build_deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_S3_REGION }}

      - name: Upload to S3 bucket dev
        run: |
          aws s3 sync s3://${{ secrets.AWS_S3_BUCKET_ENV_REPO }}/dev/${{ inputs.hash-tag }}/ s3://${{ secrets.AWS_S3_BUCKET_DEV }} --delete

      - name: Apply dev cloudfront invalidation generation
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${{ secrets.AWS_CLOUD_FRONT_ID_DEV }} \
            --path "/*"

- 롤백하고 싶은 해쉬값을 입력하면 해당하는 버전의 static files를 aws cli를 통해 S3 repo dev 디렉터리에 있는 파일을 dev 버킷에 배포한다.

- 그 후 cloudfront에 기존 버전의 해싱된 값을 제거한다.

 

 

2. github action in prod repo

(1) deploy.yaml

name: prod-test

on:
  workflow_dispatch:
    inputs:
      hash-tag:
        description: 'git commit hash name'
        required: true
        type: string

jobs:
  build_deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_S3_REGION }}

      - name: Upload to S3 bucket prod from bucket env repo
        run: |
          aws s3 sync s3://${{ secrets.AWS_S3_BUCKET_ENV_REPO }}/prod/${{ inputs.hash-tag }}/ s3://${{ secrets.AWS_S3_BUCKET_PROD }} --delete

      - name: Apply dev cloudfront invalidation generation
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${{ secrets.AWS_CLOUD_FRONT_ID_PROD }} \
            --path "/*"

- 실서버에 배포하고 싶은 해쉬값을 입력하면 해당하는 버전의 static files를 aws cli를 통해 S3 repo prod 디렉터리에 있는 파일을 prod 버킷에 배포한다.

- 그 후 cloudfront에 기존 버전의 해싱된 값을 제거한다.

 

3. aws cli

1) aws s3 cp vs sync

[1] cp는 해당 내용을 복사해서 그대로 s3 버킷에 업로드를 하는 것.

  • --recursive 옵션을 제공하여 디렉터리 아래의 모든 파일을 s3 버킷에 업로드할 수 있다
  • 그래서 cp를 사용한다면 --recursive 옵션을 일반적으로 넣어준다. (하나의 파일만 업로드할 것이 아니라면)

[2] sync는 해당 내용을 그대로 s3에 덮어씌우는 것. 

  • --delete 옵션을 제공하여 원본에 없는 파일이나 객체를 대상에서 제거할 수도 있다.
  • 그래서 sync를 사용한다면 --delete 옵션을 일반적으로 넣어준다.

2) aws cloudfront invalidation 의미

[1] invalidation(무효화)

  • 무효화 기능은 말 그대로 CloudFront 에지 로케이션에 저장된 파일의 캐시를 삭제하는 기능
  • 이걸 해줘야 이전에 캐쉬를 삭제하고 새로운 값으로 캐쉬를 적용해준다.
  • 아마존 CloudFront 세계 엣지 로케이션에 정적/동적 파일의 복사본을 캐싱합니다. 모든 엣지 로케이션에서 파일을 제거하거나 업데이트하려면 파일 또는 파일 그룹마다 무효화를 생성합니다.(aws 공식문서 참조)

 

 

references

1) github action

https://docs.github.com/en/actions

https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key

https://github.com/actions/cache

https://github.com/actions/setup-node

 

2) aws cli for s3

https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/cli-services-s3-commands.html

https://www.techdevpillar.com/blog/difference-between-s3-cp-and-sync-command/

 

3) aws cli for cloudFront

https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html

https://docs.aws.amazon.com/ko_kr/sdk-for-php/v3/developer-guide/cloudfront-example-invalidation.html