From 8299f7b139715b82d088c441df0625efc95dc922 Mon Sep 17 00:00:00 2001 From: Nicholas Rawitscher <47017130+informatter@users.noreply.github.com> Date: Wed, 20 Mar 2024 11:18:14 +0000 Subject: [PATCH] Frontend/f/ci cd v1 (#7) * 1. Updated README 2. added shell script to automate building the image for the frontend 3. Added initial CI/CD GitHubActions file 4. Modified the dockerfile so it uses the necessary environment variables to expose them to the image building process so they are available to the source code when the container is being run * Added comments * Moved github actions file from frontend dir to .github folder under root dir * set the default working directory for the ci/cd pipeline file for all jobs to the frontend directory in the project structure * small change * small change * small change * small change * small change * c --- .github/workflows/frontend_ci_cd.yml | 100 +++++++++++++++++++++++++++ frontend/.dockerignore | 3 +- frontend/build_image.sh | 18 +++++ frontend/frontend.dockerfile | 17 +++++ frontend/package.json | 3 +- 5 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/frontend_ci_cd.yml create mode 100644 frontend/build_image.sh diff --git a/.github/workflows/frontend_ci_cd.yml b/.github/workflows/frontend_ci_cd.yml new file mode 100644 index 0000000..2246e7d --- /dev/null +++ b/.github/workflows/frontend_ci_cd.yml @@ -0,0 +1,100 @@ +name: Frontend CI/CD Pipeline +# TODO run unit tests when available +run-name: Triggered by ${{ github.actor }} +on: + push: + # runs action on pushes to develop and master + branches: + - master + - develop + # runs action on PRs to develop + pull_request: + branches: + - develop + paths-ignore: + - "backend/**" + +env: + NODE_VERSION: "20" + +jobs: + linting_and_tests: + name: Linting & Unit Testing Frontend + runs-on: ubuntu-latest + defaults: + run: + #sets the working directory to the frontend for this job + working-directory: ./frontend + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Check Directory Contents + run: ls -la + + - name: Set up Node ${{env.NODE_VERSION}} + uses: actions/setup-node@v4 + with: + node-version: ${{env.NODE_VERSION}} + cache: 'npm' + cache-dependency-path: './frontend/package-lock.json' + + - name: Install Dependencies + run: npm install + - name: Check prettier version + run: npx prettier --version + - name: Run Linting + run: | + npm run lint + npm run format-check + + - name: Run Unit Tests + run: npm run test:unit + + # TODO we need to store env variables needed by the image as secrets in GitHub secrets + # so they can be used when building the image + deploy: + if: ${{github.event_name == 'push' }} + needs: linting_and_tests + name: Deploy Frontend + runs-on: ubuntu-latest + permissions: + id-token: write + defaults: + run: + #sets the working directory to the frontend dir for this job + working-directory: ./frontend + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Branch used + id: extract_branch_name + run: | + if [[ "${GITHUB_EVENT_NAME}" == "push" ]]; then + echo "::set-output name=branch::$(echo ${GITHUB_REF##*/})" + elif [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then + echo "::set-output name=branch::$(echo $GITHUB_BASE_REF)" + else + echo "::set-output name=branch::INVALID_EVENT_BRANCH_UNKNOWN" + fi + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{secrets.AWS_ACCOUNT_ID}}:role/GithHubActionsInformatter + aws-region: ${{ secrets.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + - name: Build And Push Image to AWS ECR + env: + IMAGE_TAG: ${{ steps.extract_branch_name.outputs.branch }} + REGISTRY: ${{ steps.login-ecr.outputs.registry }} + REPOSITORY: sample-ai-rag-app + run: | + docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG -f frontend.dockerfile . + docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG + +# TODO Use this command instead of the current build one: +#docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG --build-arg VITE_API_SERVER_URL="$VITE_API_SERVER_URL" --build-arg VITE_AUTH0_CALLBACK_URL="$VITE_AUTH0_CALLBACK_URL" --build-arg VITE_AUTH0_DOMAIN="$VITE_AUTH0_DOMAIN" --build-arg VITE_AUTH0_CLIENT_ID="$VITE_AUTH0_CLIENT_ID" -f frontend.dockerfile . diff --git a/frontend/.dockerignore b/frontend/.dockerignore index 6975847..4c91879 100644 --- a/frontend/.dockerignore +++ b/frontend/.dockerignore @@ -7,4 +7,5 @@ docker-compose* .gitignore README.md LICENSE -.vscode \ No newline at end of file +.vscode +.github \ No newline at end of file diff --git a/frontend/build_image.sh b/frontend/build_image.sh new file mode 100644 index 0000000..6dd0209 --- /dev/null +++ b/frontend/build_image.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Export variables from .env file excluding comments +export $(grep -v '^#' ../.env.local | xargs) + +# Substitute variables in frontend.dockerfile and save as frontend.build.dockerfile +envsubst < frontend.dockerfile > frontend.build.dockerfile + +# Build Docker image using frontend.build.dockerfile +docker build -t rag-app:local -f frontend.build.dockerfile . + +rm frontend.build.dockerfile + +# unset exported environment files from the .env.local file +# Iterate through all environment variables to unset them +for var in $(printenv | grep '^VITE_' | cut -d= -f1); do + unset $var +done \ No newline at end of file diff --git a/frontend/frontend.dockerfile b/frontend/frontend.dockerfile index fcebc0b..745f4d4 100644 --- a/frontend/frontend.dockerfile +++ b/frontend/frontend.dockerfile @@ -1,5 +1,19 @@ FROM node:lts-alpine as build-stage +ARG VITE_AUTH0_DOMAIN +ARG VITE_AUTH0_CLIENT_ID +ARG VITE_AUTH0_CALLBACK_URL +ARG VITE_API_SERVER_URL + +# We need to set the needed env variables when the image is being built. We need +# to do this because when bundling for production, the env variables are baked in the +# final boundle +ENV VITE_AUTH0_DOMAIN=$VITE_AUTH0_DOMAIN +ENV VITE_AUTH0_CLIENT_ID=$VITE_AUTH0_CLIENT_ID +ENV VITE_AUTH0_CALLBACK_URL=$VITE_AUTH0_CALLBACK_URL +ENV VITE_API_SERVER_URL=$VITE_API_SERVER_URL + + WORKDIR /app COPY package.json package-lock.json / RUN npm install @@ -9,6 +23,9 @@ RUN npm run build # production stage FROM nginx:stable-alpine as production-stage + +# All bundled files will be copied over to the html dir in Nginx to be so Nginx +# can serve them as static content COPY --from=build-stage /app/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/package.json b/frontend/package.json index 6dbe397..6d1d9fe 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,8 @@ "build-only": "vite build", "type-check": "vue-tsc --build --force", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", - "format": "prettier --write src/" + "format": "prettier --write src/", + "format-check": "prettier --check src/" }, "dependencies": { "@auth0/auth0-vue": "^2.3.3",