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",