Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
daffdee
feat: added github actions to deploy to s3 bucket
isaackps Sep 17, 2025
7031d2f
fix: syntax error
isaackps Sep 17, 2025
545fc44
fix: if error
isaackps Sep 17, 2025
5930377
fix: remove optional
isaackps Sep 17, 2025
4d683cc
fix: update deploy s3 dev actions
isaackps Sep 23, 2025
b45e3d2
fix: update deploy prod yml
isaackps Sep 23, 2025
60c6c1e
fix: indent
isaackps Sep 23, 2025
b4dc649
fix: secrets
isaackps Sep 23, 2025
5356993
fix: if statement
isaackps Sep 23, 2025
72c9ee6
fix: env
isaackps Sep 23, 2025
879b78f
fix: update actions name
isaackps Sep 23, 2025
b371486
fix: combine dev and prod
isaackps Sep 23, 2025
355485a
fix: update file
isaackps Sep 23, 2025
7a4afc2
fix: update different artifact for dev and prod
isaackps Sep 23, 2025
46ebfc0
chore: update wordings from GovTech -> IMDA (#823)
HJunyuan Sep 25, 2025
7b16e4a
fix: add maintenance notice (#824)
isaackps Sep 30, 2025
dfd1d86
fix: update readme (#825)
isaackps Sep 30, 2025
ad61676
fix: update recaptcha client key
isaackps Sep 30, 2025
72939c4
fix: update opencerts-verify package
isaackps Oct 1, 2025
cdb4447
fix: update code
isaackps Oct 1, 2025
4f976e0
fix: disable email (#826)
nghaninn Oct 2, 2025
a6a418c
fix: re-enable email
isaackps Oct 3, 2025
6b87cf2
fix: update CICD pipeline
isaackps Oct 9, 2025
9ea9442
fix: update readme
isaackps Oct 9, 2025
eb5ad89
fix: update ci to run lint and test first
isaackps Oct 9, 2025
3d16fc9
fix: update dev env actions
isaackps Oct 9, 2025
4855980
fix: update prod deployment script
isaackps Oct 9, 2025
7cc335c
fix: update dev api end point
isaackps Oct 9, 2025
0bcf758
fix: dev actions (#827)
isaackps Oct 21, 2025
3d5dd00
fix: update prod deployment script to be manually triggered (#828)
isaackps Oct 28, 2025
dc768d7
Fix/branch develop (#830)
isaackps Nov 4, 2025
08e9b00
Merge branch 'master' into develop
isaackps Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions .circleci/config.yml

This file was deleted.

39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI - Lint and Test

on:
push:
branches: [develop, master]
pull_request:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

env:
NODE_VERSION: "18"

jobs:
lint-and-test:
name: Lint & Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"

- name: Install dependencies
run: npm ci

- name: Type check
run: npm run type-check --if-present

- name: Lint
run: npm run lint

- name: Unit tests
run: npm test -- --ci
111 changes: 111 additions & 0 deletions .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
name: Deploy to Dev Environment

on:
push:
branches: [develop]

concurrency:
group: deploy-dev-${{ github.ref }}
cancel-in-progress: true

env:
NODE_VERSION: "18"
BUILD_DIR: "out"

jobs:
wait-for-ci:
name: Wait for CI
runs-on: ubuntu-latest
steps:
- name: Wait for CI workflow
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.ref }}
check-name: 'Lint & Test'
repo-token: ${{ secrets.GITHUB_TOKEN }}

build-dev:
name: Build (Dev)
runs-on: ubuntu-latest
needs: wait-for-ci
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"

- name: Install dependencies
run: npm ci

- name: Build static site
run: |
npm run build
npm run postexport
env:
# Build-time envs used in next.config.js
NET: 'sepolia'
INFURA_API_KEY: ${{ secrets.DEV_INFURA_API_KEY }}
ALCHEMY_API_KEY: ${{ secrets.DEV_ALCHEMY_API_KEY }}
GA4_TAG_ID: ${{ secrets.GA4_TAG_ID }}
TRUSTED_TLDS: ${{ secrets.TRUSTED_TLDS }}

- name: Upload build artifact (Dev)
uses: actions/upload-artifact@v4
with:
name: static-site-dev
path: ${{ env.BUILD_DIR }}

deploy-dev:
name: Deploy to S3 (Dev)
needs: build-dev
runs-on: ubuntu-latest
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: static-site-dev
path: ${{ env.BUILD_DIR }}

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Select target bucket
id: bucket
run: |
echo "bucket=${S3_BUCKET_DEV}" >> $GITHUB_OUTPUT
env:
S3_BUCKET_DEV: ${{ secrets.S3_BUCKET_DEV }}

- name: Sync static assets with long cache
run: |
aws s3 sync $BUILD_DIR s3://${{ steps.bucket.outputs.bucket }} \
--delete \
--exclude "*" \
--include "_next/*" \
--include "static/*" \
--cache-control "public, max-age=31536000, immutable"

- name: Sync HTML and other assets with no-cache
run: |
aws s3 sync $BUILD_DIR s3://${{ steps.bucket.outputs.bucket }} \
--delete \
--exclude "_next/*" \
--exclude "static/*" \
--cache-control "no-cache, no-store, must-revalidate"

- name: Invalidate CloudFront
env:
CLOUDFRONT_DISTRIBUTION_ID_DEV: ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID_DEV }}
if: ${{ env.CLOUDFRONT_DISTRIBUTION_ID_DEV != '' }}
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID_DEV }} \
--paths "/*"
110 changes: 110 additions & 0 deletions .github/workflows/deploy-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Deploy to Production Environment

on:
workflow_dispatch:

concurrency:
group: deploy-prod-${{ github.ref }}
cancel-in-progress: true

env:
NODE_VERSION: "18"
BUILD_DIR: "out"

jobs:
wait-for-ci:
name: Wait for CI
runs-on: ubuntu-latest
steps:
- name: Wait for CI workflow
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.ref }}
check-name: 'Lint & Test'
repo-token: ${{ secrets.GITHUB_TOKEN }}

build-prod:
name: Build (Prod)
runs-on: ubuntu-latest
needs: wait-for-ci
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"

- name: Install dependencies
run: npm ci

- name: Build static site
run: |
npm run build
npm run postexport
env:
# Build-time envs used in next.config.js
NET: 'mainnet'
INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }}
ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }}
GA4_TAG_ID: ${{ secrets.GA4_TAG_ID }}
TRUSTED_TLDS: ${{ secrets.TRUSTED_TLDS }}

- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: static-site-prod
path: ${{ env.BUILD_DIR }}

deploy-prod:
name: Deploy to S3 (Prod)
needs: build-prod
runs-on: ubuntu-latest
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: static-site-prod
path: ${{ env.BUILD_DIR }}

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

- name: Select target bucket
id: bucket
run: |
echo "bucket=${S3_BUCKET_PROD}" >> $GITHUB_OUTPUT
env:
S3_BUCKET_PROD: ${{ secrets.S3_BUCKET_PROD }}

- name: Sync static assets with long cache
run: |
aws s3 sync $BUILD_DIR s3://${{ steps.bucket.outputs.bucket }} \
--delete \
--exclude "*" \
--include "_next/*" \
--include "static/*" \
--cache-control "public, max-age=31536000, immutable"

- name: Sync HTML and other assets with no-cache
run: |
aws s3 sync $BUILD_DIR s3://${{ steps.bucket.outputs.bucket }} \
--delete \
--exclude "_next/*" \
--exclude "static/*" \
--cache-control "no-cache, no-store, must-revalidate"

- name: Invalidate CloudFront
env:
CLOUDFRONT_DISTRIBUTION_ID_PROD: ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID_PROD }}
if: ${{ env.CLOUDFRONT_DISTRIBUTION_ID_PROD != '' }}
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID_PROD }} \
--paths "/*"
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v18.20.3
v18
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
# Certificate Web UI

[![CircleCI](https://circleci.com/gh/OpenCerts/opencerts-website.svg?style=svg)](https://circleci.com/gh/OpenCerts/opencerts-website)
[![CI](https://github.com/OpenCerts/opencerts-website/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenCerts/opencerts-website/actions/workflows/ci.yml)
[![Deploy Dev](https://github.com/OpenCerts/opencerts-website/actions/workflows/deploy-dev.yml/badge.svg)](https://github.com/OpenCerts/opencerts-website/actions/workflows/deploy-dev.yml)
[![Deploy Prod](https://github.com/OpenCerts/opencerts-website/actions/workflows/deploy-prod.yml/badge.svg)](https://github.com/OpenCerts/opencerts-website/actions/workflows/deploy-prod.yml)

## Notice

#### 🚧 Scheduled Maintenance Notice 🚧

OpenCerts services will be undergoing scheduled maintenance from **30 September to 1 October**.
During this period, the platform may be unavailable or experience interruptions.

We appreciate your patience and understanding as we work to improve our services.
From 1 Oct 2025, the Infocomm Media Development Authority (IMDA) will take over the maintenance of OpenCerts. For enquiries, reach out to https://trustvc.io

---

Expand Down Expand Up @@ -104,3 +101,9 @@ Try running `npm rebuild`
### Integration tests

To run integration tests locally, make sure you run `npm run build` once to build the static site first. The e2e tests will then spin up a server based on the `out` folder in project root.

### Deployment

develop branch is deployed to https://dev.opencerts.io -> for development and testing purposes only.

master branch is deployed to https://opencerts.io -> for production use.
1 change: 0 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const nextConfig = {
ALCHEMY_API_KEY: process.env.ALCHEMY_API_KEY, // The default/free key should not be used in production as they are rate-limited by the service provider
TRUSTED_TLDS: process.env.TRUSTED_TLDS || "gov.sg,edu.sg",
GA4_TAG_ID: process.env.GA4_TAG_ID || "G-JP12T2F01V",
WOGAA_ENV: process.env.WOGAA_ENV || "production",
},
// Variables passed to both server and client
publicRuntimeConfig: {
Expand Down
Loading