This CI pipeline streamlines the building and deployment of static applications to an S3 bucket, coupled with automatic CloudFront cache invalidation.
- App Build Process: Automates the build of your static application.
- S3 Upload with Cache-Control: Efficiently uploads your built application to S3 with optimized cache control settings.
- Automatic CloudFront Invalidation: Ensures immediate content updates by invalidating CloudFront cache after deployment.
- Multi-environment Support: Configurable for different deployment environments (e.g., Stage, Production).
To ensure dynamic routing and seamless integration, configure your frontend project (e.g., with Vite + React) as follows:
- React Router DOM: When using
react-router-dom
withcreateBrowserRouter
, set thebasename
using the environment variableimport.meta.env.VITE_BROWSER_ROUTER_BASENAME
. This variable will be exposed during the CI build process. - Vite Configuration: In your
vite.config.ts
, define thebase
property like this:base: process.env.VITE_BROWSER_ROUTER_BASENAME || '/',
During the CI build process, the value of the PREVIEW_PREFIX
environment variable is used to define the basename (or base path) of the application — i.e., the subdirectory where the app will be served (e.g., /preview-123/
).
The following environment variables are exported and customized for each supported framework to ensure proper routing behavior when deployed under a subpath:
export VITE_BROWSER_ROUTER_BASENAME="/${{ env.PREVIEW_PREFIX }}"
export PUBLIC_URL="/${{ env.PREVIEW_PREFIX }}"
export NEXT_PUBLIC_BASENAME="/${{ env.PREVIEW_PREFIX }}"
export NG_APP_BASENAME="/${{ env.PREVIEW_PREFIX }}/"
export VUE_APP_BASENAME="/${{ env.PREVIEW_PREFIX }}"
- Variable:
VITE_BROWSER_ROUTER_BASENAME
- Usage: Passed to
<BrowserRouter basename={...}>
and "base" property in vite.config - Accessed via:
import.meta.env.VITE_BROWSER_ROUTER_BASENAME
- Variable:
PUBLIC_URL
- Usage: Passed to
<BrowserRouter basename={...}>
- Accessed via:
process.env.PUBLIC_URL
- Variable:
NEXT_PUBLIC_BASENAME
- Usage: Used for custom route handling or asset paths
- Accessed via:
process.env.NEXT_PUBLIC_BASENAME
- Variable:
NG_APP_BASENAME
- Usage: Used as
APP_BASE_HREF
or passed to--base-href
during build - Accessed via: Depends on strategy (recommends
@ngx-env/builder
)
- Variable:
VUE_APP_BASENAME
- Usage: Used to configure
publicPath
invue.config.js
- Accessed via:
process.env.VUE_APP_BASENAME
Each variable follows the environment conventions of its respective framework and should be used during build time or app initialization. This ensures the application works correctly when deployed under a subdirectory (/${PREVIEW_PREFIX}/
).
When deploying a Single Page Application (SPA) using Static Site Generation (SSG) — such as with Vite — to environments like Amazon S3, you often serve your site under a subpath (e.g., https://example.com/my-app/
) instead of the root (/
).
By setting the basename
in your router and the base
in your Vite config, you ensure:
React Router knows that all routes should be resolved relative to the subpath.
JS, CSS, and other static assets will be linked using the correct base path (e.g., /my-app/assets/...
) in the generated index.html
.
The app may break when accessed from a subdirectory:
- Routes may return 404
- Static assets may fail to load
Avoid broken links and routing issues by ensuring the subpath used in your configuration matches the one used during deployment — regardless of the framework or setup you're using.
To set up the CI/CD pipeline, you need to create a .github/workflows
folder in the root of your repository. Inside this folder, add the following workflow files:
start_clear_preview.yml
start_push_preview.yml
start_push_prod_release.yml
start_push_stage_release.yml
For the CI pipeline to function correctly, you must add the following secrets to your repository's "Actions" settings to each environment
:
- Should create
stage
andprod
environments.
Secrets for your stage
environment:
AWS_ACCESS_KEY_ID
: Your AWS IAM access key ID.AWS_SECRET_ACCESS_KEY
: Your AWS IAM secret access key.AWS_REGION
: The AWS region where your S3 bucket is located.S3_BUCKET_NAME
: The name of your S3 bucket for the stage environment.CLOUDFRONT_DISTRIBUTION_ID
: The CloudFront distribution ID for the stage environment.WF_GITHUB_TOKEN
: A GitHub classic token withrepo
permissions, used for workflow operations.
Secrets for your prod
environment:
AWS_ACCESS_KEY_ID
: Your AWS IAM access key ID.AWS_SECRET_ACCESS_KEY
: Your AWS IAM secret access key.AWS_REGION
: The AWS region where your S3 bucket is located.S3_BUCKET_NAME
: The name of your S3 bucket for the production environment.CLOUDFRONT_DISTRIBUTION_ID
: The CloudFront distribution ID for the production environment.WF_GITHUB_TOKEN
: A GitHub classic token withrepo
permissions, used for workflow operations.
For the CI pipeline to function correctly, you must add the following variables to your repository's "Actions" settings to each environment
:
- Go to: GitHub repository -> Settings -> Secrets and variables -> Actions -> Variables -> New repository variable
Variables for your stage
environment:
STAGE_PROJECT_BUILD_ENVS
: Your FRONT-END project envs ofstage
environment.
Variables for your prod
environment:
PROJECT_BUILD_ENVS
: Your FRONT-END project envs ofprod
environment.
run_tests
: Enables or disables running the test suite and uploading the coverage report.run_lint
: Enables or disables the commit message linting step.run_tsc
: Enables or disables the TypeScript build and type checking step.has_semantic_release
: Enables or disables the release creation.project_build_envs
: Receive envs of builded Front-end project.environment_type
: Define environment,stage
orprod
.