diff --git a/.github/workflows/cicd-stg.yaml b/.github/workflows/cicd-stg.yaml new file mode 100644 index 00000000..ec63fef9 --- /dev/null +++ b/.github/workflows/cicd-stg.yaml @@ -0,0 +1,137 @@ +name: "CICD staging" + +on: + # Test run before merging + pull_request: + branches: + - main + # On merged + push: + branches: + - main + - users/richard/76-docker-build-and-host-dependency + +jobs: + build-makefile: + permissions: + id-token: write + contents: write + runs-on: ubuntu-22.04 + # To test deployments, remove the github.ref_name clause: see devops/docs/z2-testing-apps.md - rrw 2024-04-12 + # && github.ref_name == 'main' + if: github.actor != 'dependabot[bot]' + name: "Build image with Makefile" + strategy: + fail-fast: false + matrix: + application: [otterscan] + include: + - application: otterscan + image_name: otterscan + path: . + tag_length: 8 + tag_latest: false + env: + DOCKER_DOMAIN: asia-docker.pkg.dev + REGISTRY: asia-docker.pkg.dev/prj-d-devops-services-4dgwlsse/zilliqa-public + steps: + - name: Checkout code + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + with: + submodules: recursive + ref: ${{ github.event.pull_request.head.ref }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + fetch-depth: 0 + + - name: "Authenticate to Google Cloud - staging" + id: google-auth + uses: "google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa" + with: + token_format: "access_token" + workload_identity_provider: "${{ secrets.GCP_PRD_GITHUB_WIF }}" + service_account: "${{ secrets.GCP_STG_GITHUB_SA_DOCKER_REGISTRY }}" + create_credentials_file: true + + - name: Login to the registry - staging + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 + with: + registry: ${{ env.DOCKER_DOMAIN }} + username: "oauth2accesstoken" + password: "${{ steps.google-auth.outputs.access_token }}" + + - name: Get tag version - staging + id: set-tag + uses: Zilliqa/gh-actions-workflows/actions/generate-tag@v1 + with: + tag: ${{ env.REGISTRY }}/${{ matrix.image_name }} + length: ${{ matrix.tag_length }} + + - name: "Build and push ${{ matrix.application }} - staging" + env: + ENVIRONMENT: stg + IMAGE_TAG: ${{ steps.set-tag.outputs.tags }} + run: | + cd ${{ matrix.path }} + make image/build-and-push + + - name: "Build and push ${{ matrix.application }} tag latest - staging" + if: ${{ matrix.tag_latest == true }} + env: + ENVIRONMENT: stg + IMAGE_TAG: "${{ env.REGISTRY }}/${{ matrix.image_name }}:latest" + run: | + cd ${{ matrix.path }} + make image/build-and-push + + deploy-to-staging: + needs: [build-makefile] + permissions: + id-token: write + contents: write + runs-on: ubuntu-22.04 + if: github.actor != 'dependabot[bot]' && github.ref_name == 'main' + strategy: + fail-fast: false + matrix: + application: + - developer-portal + env: + APP_NAME: ${{ matrix.application }} + Z_ENV: infra/live/gcp/non-production/prj-d-staging/z_ase1.yaml + Z_SERVICE_ACCOUNT: ${{ secrets.GCP_STG_GITHUB_SA_K8S_DEPLOY }} + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_STG }} + GITHUB_PAT: ${{ secrets.GH_PAT }} + Z_IMAGE: asia-docker.pkg.dev/prj-d-devops-services-4dgwlsse/zilliqa-private/z:latest + REGISTRY: asia-docker.pkg.dev + steps: + - name: Checkout + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + with: + repository: Zilliqa/devops + token: ${{ env.GITHUB_PAT }} + ref: main + sparse-checkout: | + ${{ env.Z_ENV }} + + - name: Authenticate to Google Cloud + id: google-auth + uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa + with: + token_format: "access_token" + workload_identity_provider: "${{ secrets.GCP_PRD_GITHUB_WIF }}" + service_account: ${{ env.Z_SERVICE_ACCOUNT }} + create_credentials_file: true + + - name: Deploy application + run: | + gcloud auth print-access-token | docker login -u oauth2accesstoken --password-stdin https://${{ env.REGISTRY }} + docker run --rm \ + -e ZQ_USER='${{ env.Z_SERVICE_ACCOUNT }}' \ + -e Z_ENV='/devops/${{ env.Z_ENV }}' \ + -e OP_SERVICE_ACCOUNT_TOKEN='${{ env.OP_SERVICE_ACCOUNT_TOKEN }}' \ + -e GITHUB_PAT='${{ env.GITHUB_PAT }}' \ + -e CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE='/google/application_default_credentials.json' \ + -v `pwd`:/devops \ + -v ${{ steps.google-auth.outputs.credentials_file_path }}:/google/application_default_credentials.json \ + --name z_container ${{ env.Z_IMAGE }} \ + bash -c "gcloud config set account ${{ env.Z_SERVICE_ACCOUNT }} && z /app /devops app sync --cache-dir .cache ${{ env.APP_NAME }}" diff --git a/.github/workflows/docker-publish.yaml b/.github/workflows/docker-publish.yaml index c34576bb..cab175fc 100644 --- a/.github/workflows/docker-publish.yaml +++ b/.github/workflows/docker-publish.yaml @@ -83,14 +83,11 @@ jobs: type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} type=semver,pattern={{raw}} - - name: Build and push by digest - id: build - uses: docker/build-push-action@v5 - with: - context: . - push: true - platforms: ${{ matrix.platform }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: "Build and push ${{ matrix.application }}" + env: + ENVIRONMENT: stg + IMAGE_TAG: ${{ steps.set-tag.outputs.tags }} + run: | + cd ${{ matrix.path }} + make image/build-and-push + diff --git a/.github/workflows/pages-deployment.yaml b/.github/workflows/pages-deployment.yaml deleted file mode 100644 index 441d995a..00000000 --- a/.github/workflows/pages-deployment.yaml +++ /dev/null @@ -1,38 +0,0 @@ -on: - workflow_call: - secrets: - apiToken: - required: true - accountId: - required: true - projectName: - required: true - viteConfigJson: - required: true - -jobs: - deploy-cloudflare: - runs-on: ubuntu-latest - permissions: - contents: read - deployments: write - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install node - uses: actions/setup-node@v4 - with: - node-version-file: ".nvmrc" - cache: "npm" - - name: Install packages - run: npm ci - - name: Build Otterscan - run: npm run build - env: - VITE_CONFIG_JSON: ${{ secrets.viteConfigJson }} - - name: Publish - uses: cloudflare/wrangler-action@v3 - with: - apiToken: ${{ secrets.apiToken }} - accountId: ${{ secrets.accountId }} - command: pages deploy dist --project-name=${{ secrets.projectName }} --commit-dirty=true diff --git a/Dockerfile.zilliqa b/Dockerfile.zilliqa new file mode 100644 index 00000000..c36e3bbb --- /dev/null +++ b/Dockerfile.zilliqa @@ -0,0 +1,26 @@ +FROM node:22.9.0-alpine3.19 AS builder +WORKDIR /otterscan-build +COPY --link ["package.json", "package-lock.json", "/otterscan-build/"] +RUN npm ci --fetch-timeout 6000000 --verbose +COPY --link ["run-nginx.sh", "tsconfig.json", "tsconfig.node.json", "postcss.config.js", "tailwind.config.js", "vite.config.ts", "index.html", "/otterscan-build/"] +COPY --link ["public", "/otterscan-build/public/"] +COPY --link ["src", "/otterscan-build/src/"] +COPY --link ["autogen", "/otterscan-build/autogen/"] +RUN npm run just-build + +FROM nginx:1.27.3-alpine3.20 +RUN set -ex \ + && apk update \ + && apk add nginx-mod-http-brotli jq +WORKDIR /usr/share/nginx/html/ +COPY --link --from=otterscan/otterscan-assets:v1.1.1 /usr/share/nginx/html/chains chains/ +COPY --link --from=otterscan/otterscan-assets:v1.1.1 /usr/share/nginx/html/topic0 topic0/ +COPY --link --from=otterscan/otterscan-assets:v1.1.1 /usr/share/nginx/html/assets assets/ +COPY --link --from=otterscan/otterscan-assets:v1.1.1 /usr/share/nginx/html/signatures signatures/ +COPY --link nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf +COPY --link nginx/nginx.conf /etc/nginx/nginx.conf +COPY --link --from=builder /otterscan-build/dist /usr/share/nginx/html/ +COPY --link --from=builder /otterscan-build/run-nginx.sh / +WORKDIR / + +CMD ["/run-nginx.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..3007f55e --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +.PHONY: all +all: image/build-and-push + +.ONESHELL: +SHELL := /bin/bash +.SHELLFLAGS = -ec + +ENVIRONMENT ?= dev +VALID_ENVIRONMENTS := dev stg prd +# Check if the ENVIRONMENT variable is in the list of valid environments +ifeq ($(filter $(ENVIRONMENT),$(VALID_ENVIRONMENTS)),) +$(error Invalid value for ENVIRONMENT. Valid values are dev, stg, or prd.) +endif + +HERE=$(shell pwd) + +IMAGE_TAG ?= otterscan:latest + + +.PHONY: image/build-and-push +image/build-and-push: + ./scripts/gen-version.sh autogen/version.ts + docker buildx build -f Dockerfile.zilliqa . -t $(IMAGE_TAG) diff --git a/package.json b/package.json index 0f90d375..e27c953c 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "build": "./scripts/gen-version.sh autogen/version.ts && tsc && vite build", "preview": "./scripts/gen-version.sh autogen/version.ts && vite preview", "test": "jest", + "just-build": "tsc && vite build", "source-map-explorer": "source-map-explorer build/static/js/*.js", "assets-start": "docker run --rm -p 5175:80 --name otterscan-assets -d otterscan/otterscan-assets:v1.0.1", "assets-stop": "docker stop otterscan-assets", diff --git a/src/useConfig.ts b/src/useConfig.ts index 1e65b801..e138e970 100644 --- a/src/useConfig.ts +++ b/src/useConfig.ts @@ -218,7 +218,7 @@ export type OtterscanConfig = { /** Version number */ - version: string; + version?: string; /** Chain connections */ @@ -371,13 +371,15 @@ export const loadOtterscanConfig = async (): Promise => { var host = window.location.host; var connections = storageConfiguration["connections"] ?? config.connections; - for (var c of connections) { - const hosts = c.hostnames; - if (hosts !== undefined) { - for (var h of hosts) { - if (host.startsWith(h)) { - if (!("erigonURL" in storageConfiguration)) { - storageConfiguration["erigonURL"] = c.url; + if (connections !== undefined) { + for (var c of connections) { + const hosts = c.hostnames; + if (hosts !== undefined) { + for (var h of hosts) { + if (host.startsWith(h)) { + if (!("erigonURL" in storageConfiguration)) { + storageConfiguration["erigonURL"] = c.url; + } } } }