Skip to content

fix: repair app install QR redirects #395

fix: repair app install QR redirects

fix: repair app install QR redirects #395

# Build showcase images (tag pr-<number>), Helm install/upgrade per PR, register PR webhook with Traction, optional URL comment.
#
# Shared Docker steps live under `.github/actions/showcase-build-*` (also used by deploy-showcase-dev).
#
# Configure on bcgov/BC-Wallet-Demo (repository Actions secrets):
# Secrets: OPENSHIFT_SERVER, OPENSHIFT_TOKEN, OPENSHIFT_DEV_NAMESPACE
# Pre-create OpenShift Secret `showcase-traction` in OPENSHIFT_DEV_NAMESPACE (shared with dev deploy).
# Optional variable: SHOWCASE_PR_HOST_SUFFIX — hostname without scheme (overrides workflow default).
# Default is Silver dev ingress (see env.SHOWCASE_PR_HOST_SUFFIX). Public URL:
# https://pr-<N>-<suffix>/digital-trust/showcase
# Optional build-args (same as build_packages): REACT_APP_* via repo Variables or Secrets.
#
# Helm 3 stores release metadata in the target namespace (default: Secrets; optional: ConfigMaps).
# The OpenShift token must be allowed to list (and create/update/delete/get) that resource type there.
#
# Skips when not bcgov, on draft PRs (no deploy), or when OpenShift secrets are missing at deploy time.
# Expect PR branches on bcgov/BC-Wallet-Demo (same-repo PRs) so Actions secrets/vars apply; fork PRs lack secrets.
name: Showcase PR — build and deploy
on:
pull_request:
branches: [main]
paths:
- 'charts/showcase/**'
- 'deploy/showcase/**'
- 'frontend/**'
- 'server/**'
- 'package.json'
- 'yarn.lock'
- '.github/workflows/deploy-showcase-pr.yaml'
- '.github/actions/showcase-build-server/**'
- '.github/actions/showcase-build-frontend/**'
- '.github/actions/showcase-setup-oc-helm/**'
- '.github/actions/showcase-helm-lint/**'
- '.github/scripts/showcase-traction-webhook.sh'
types: [opened, synchronize, reopened, ready_for_review]
draft: false
concurrency:
group: showcase-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true
# GHCR push needs packages:write; orgs may also require Actions "Read and write" workflow permissions
# and linking the repo to the package. ghcr login uses repository_owner + GITHUB_TOKEN (see showcase-build-* actions).
permissions:
contents: read
packages: write
pull-requests: write
env:
HUSKY: '0'
REGISTRY: ghcr.io
SHOWCASE_SERVER_IMAGE: ghcr.io/${{ github.repository_owner }}/digital-trust-showcase-server
SHOWCASE_FRONTEND_IMAGE: ghcr.io/${{ github.repository_owner }}/digital-trust-showcase-frontend
# PR Route host fragment (no scheme): https://pr-<N>-<SHOWCASE_PR_HOST_SUFFIX>/…
# Override per-repo with Actions variable SHOWCASE_PR_HOST_SUFFIX if your cluster DNS differs.
SHOWCASE_PR_HOST_SUFFIX: ${{ vars.SHOWCASE_PR_HOST_SUFFIX != '' && vars.SHOWCASE_PR_HOST_SUFFIX || 'digital-trust-showcase-dev.apps.silver.devops.gov.bc.ca' }}
# Traction tenant proxy for PR webhook registration (matches deploy/showcase/values-pr.yaml).
TRACTION_URL: 'https://traction-tenant-proxy-dev.apps.silver.devops.gov.bc.ca'
jobs:
ready:
name: Ready gates
runs-on: ubuntu-latest
outputs:
deploy: ${{ github.repository_owner == 'bcgov' && github.event.pull_request.draft != true }}
build: ${{ github.repository_owner == 'bcgov' }}
steps:
- name: Compute gate outputs
run: 'true'
build_server:
name: Build and push server image
runs-on: ubuntu-latest
timeout-minutes: 45
needs: [ready]
if: needs.ready.outputs.build == 'true'
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: ./.github/actions/showcase-build-server
with:
image: ${{ env.SHOWCASE_SERVER_IMAGE }}
tag: pr-${{ github.event.pull_request.number }}
github_token: ${{ secrets.GITHUB_TOKEN }}
build_frontend:
name: Build and push frontend image
runs-on: ubuntu-latest
timeout-minutes: 45
needs: [ready]
if: needs.ready.outputs.build == 'true'
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: ./.github/actions/showcase-build-frontend
with:
image: ${{ env.SHOWCASE_FRONTEND_IMAGE }}
tag: pr-${{ github.event.pull_request.number }}
react_app_host_backend: https://pr-${{ github.event.pull_request.number }}-${{ env.SHOWCASE_PR_HOST_SUFFIX }}
react_app_insights_project_id: ${{ vars.REACT_APP_INSIGHTS_PROJECT_ID || secrets.REACT_APP_INSIGHTS_PROJECT_ID }}
github_token: ${{ secrets.GITHUB_TOKEN }}
deploy:
name: Helm upgrade (PR instance)
runs-on: ubuntu-latest
timeout-minutes: 20
needs: [ready, build_server, build_frontend]
# Job-level `if` cannot use `secrets` (GitHub restriction). Verify OpenShift secrets in-step.
if: ${{ always() && needs.ready.outputs.deploy == 'true' && needs.build_server.result == 'success' && needs.build_frontend.result == 'success' }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Verify OpenShift secrets for deploy
env:
OPENSHIFT_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }}
OPENSHIFT_SERVER: ${{ secrets.OPENSHIFT_SERVER }}
OPENSHIFT_DEV_NAMESPACE: ${{ secrets.OPENSHIFT_DEV_NAMESPACE }}
run: |
if [[ -z "${OPENSHIFT_TOKEN}" || -z "${OPENSHIFT_SERVER}" || -z "${OPENSHIFT_DEV_NAMESPACE}" ]]; then
echo '::error::Missing OPENSHIFT_SERVER, OPENSHIFT_TOKEN, or OPENSHIFT_DEV_NAMESPACE for showcase PR deploy.'
exit 1
fi
- uses: ./.github/actions/showcase-setup-oc-helm
- uses: redhat-actions/oc-login@5eb45e848b168b6bf6b8fe7f1561003c12e3c99d # v1.3
with:
openshift_server_url: ${{ secrets.OPENSHIFT_SERVER }}
openshift_token: ${{ secrets.OPENSHIFT_TOKEN }}
namespace: ${{ secrets.OPENSHIFT_DEV_NAMESPACE }}
- name: Helm release storage RBAC
env:
OPENSHIFT_DEV_NAMESPACE: ${{ secrets.OPENSHIFT_DEV_NAMESPACE }}
run: |
set -euo pipefail
# Do not use `oc project -q`: some CI tokens cannot *view* the Project but can still act in the namespace.
ns="${OPENSHIFT_DEV_NAMESPACE}"
if [[ -z "${ns}" ]]; then
echo '::error::OPENSHIFT_DEV_NAMESPACE is empty.'
exit 1
fi
if oc auth can-i list secrets -n "${ns}" --quiet >/dev/null 2>&1; then
echo "Helm will use default Secret release storage in namespace ${ns}."
elif oc auth can-i list configmaps -n "${ns}" --quiet >/dev/null 2>&1; then
echo "HELM_DRIVER=configmap" >> "${GITHUB_ENV}"
echo "Helm will use ConfigMap release storage (list secrets denied in ${ns})."
else
echo '::notice::oc whoami: '"$(oc whoami 2>&1 || true)"
echo '::notice::SubjectAccessReview list secrets:'
oc auth can-i list secrets -n "${ns}" 2>&1 || true
echo '::notice::SubjectAccessReview list configmaps:'
oc auth can-i list configmaps -n "${ns}" 2>&1 || true
echo '::error::Helm cannot run: this token must be allowed to list Secrets or ConfigMaps in namespace '"${ns}"' for Helm 3 release history (https://helm.sh/docs/topics/advanced/). Grant the CI service account get,list,create,update,patch,delete on secrets or on configmaps in that namespace (same pattern as bcgov/traction PR deploy).'
exit 1
fi
- uses: ./.github/actions/showcase-helm-lint
with:
skip_checkout: 'true'
skip_helm_install: 'true'
- name: Helm upgrade --install
working-directory: charts/showcase
env:
PR_NUM: ${{ github.event.pull_request.number }}
HOST_SUFFIX: ${{ env.SHOWCASE_PR_HOST_SUFFIX }}
OWNER_LOWER: ${{ github.repository_owner }}
OPENSHIFT_DEV_NAMESPACE: ${{ secrets.OPENSHIFT_DEV_NAMESPACE }}
run: |
set -euo pipefail
origin="https://pr-${PR_NUM}-${HOST_SUFFIX}"
owner_lc="$(echo "${OWNER_LOWER}" | tr '[:upper:]' '[:lower:]')"
ns="${OPENSHIFT_DEV_NAMESPACE}"
if ! oc get secret showcase-traction -n "${ns}" >/dev/null 2>&1; then
echo '::warning::Secret showcase-traction not found in '"${ns}"' — create it before deploy (see deploy/showcase/values-pr.yaml).'
fi
helm dependency update
helm_args=(
-f ../../deploy/showcase/values-pr.yaml
--namespace "${ns}"
--set-string "showcase.publicOrigin=${origin}"
--set "showcase.server.image.repository=${owner_lc}/digital-trust-showcase-server"
--set "showcase.server.image.tag=pr-${PR_NUM}"
--set "showcase.frontend.image.repository=${owner_lc}/digital-trust-showcase-frontend"
--set "showcase.frontend.image.tag=pr-${PR_NUM}"
--wait
--timeout 10m
)
if ! helm upgrade --install "pr-${PR_NUM}-showcase" . "${helm_args[@]}"; then
echo '::error::helm upgrade failed; status and recent events follow.'
helm status "pr-${PR_NUM}-showcase" -n "${OPENSHIFT_DEV_NAMESPACE}" 2>/dev/null || true
oc get events -n "${OPENSHIFT_DEV_NAMESPACE}" --sort-by='.lastTimestamp' 2>/dev/null | tail -40 || true
inst="pr-${PR_NUM}-showcase"
p="$(
oc get pods -n "${OPENSHIFT_DEV_NAMESPACE}" \
-l "app.kubernetes.io/component=server,app.kubernetes.io/instance=${inst}" \
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true
)"
if [[ -n "${p}" ]]; then
echo '::notice::--- oc describe pod '"${p}"' (tail) ---'
oc describe pod "${p}" -n "${OPENSHIFT_DEV_NAMESPACE}" 2>/dev/null | tail -80 || true
echo '::notice::--- oc logs '"${p}"' -c wait-for-mongo-tcp (tail) ---'
oc logs "${p}" -n "${OPENSHIFT_DEV_NAMESPACE}" -c wait-for-mongo-tcp --tail=60 2>/dev/null || true
echo '::notice::--- oc logs '"${p}"' -c server (tail) ---'
oc logs "${p}" -n "${OPENSHIFT_DEV_NAMESPACE}" -c server --tail=80 2>/dev/null || true
fi
exit 1
fi
# Same image tag (:pr-N) may point at a new digest; restart pulls new layers. Wait so the job does not succeed before pods are ready.
- name: Restart deployments and wait for rollouts
env:
PR_NUM: ${{ github.event.pull_request.number }}
OPENSHIFT_DEV_NAMESPACE: ${{ secrets.OPENSHIFT_DEV_NAMESPACE }}
run: |
set -euo pipefail
ns="${OPENSHIFT_DEV_NAMESPACE}"
oc rollout restart "deployment/pr-${PR_NUM}-showcase-server" -n "${ns}"
oc rollout status "deployment/pr-${PR_NUM}-showcase-server" -n "${ns}" --timeout=10m
oc rollout restart "deployment/pr-${PR_NUM}-showcase-frontend" -n "${ns}"
oc rollout status "deployment/pr-${PR_NUM}-showcase-frontend" -n "${ns}" --timeout=10m
# Append this PR's webhook to the shared Traction tenant; other registered URLs are preserved.
- name: Register PR webhook with Traction
env:
PR_NUM: ${{ github.event.pull_request.number }}
SHOWCASE_PR_HOST_SUFFIX: ${{ env.SHOWCASE_PR_HOST_SUFFIX }}
TRACTION_URL: ${{ env.TRACTION_URL }}
OPENSHIFT_DEV_NAMESPACE: ${{ secrets.OPENSHIFT_DEV_NAMESPACE }}
run: .github/scripts/showcase-traction-webhook.sh add
pr_urls_comment:
name: PR deployment comment
runs-on: ubuntu-latest
needs: [ready, deploy]
if: ${{ always() && needs.ready.outputs.deploy == 'true' && needs.deploy.result == 'success' }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: <!-- showcase-pr-url -->
- name: Create PR deployment comment
if: steps.fc.outputs.comment-id == ''
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
issue-number: ${{ github.event.pull_request.number }}
body: |
<!-- showcase-pr-url -->
| Showcase PR | |
| --- | --- |
| UI (same host as API) | <a href="https://pr-${{ github.event.pull_request.number }}-${{ env.SHOWCASE_PR_HOST_SUFFIX }}/digital-trust/showcase" target="_blank" rel="noopener noreferrer">https://pr-${{ github.event.pull_request.number }}-${{ env.SHOWCASE_PR_HOST_SUFFIX }}/digital-trust/showcase</a> |
Showcase PR deployment URL (Helm release `pr-${{ github.event.pull_request.number }}-showcase`).
- name: Update PR deployment comment
if: steps.fc.outputs.comment-id != ''
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.fc.outputs.comment-id }}
edit-mode: replace
body: |
<!-- showcase-pr-url -->
| Showcase PR | |
| --- | --- |
| UI (same host as API) | <a href="https://pr-${{ github.event.pull_request.number }}-${{ env.SHOWCASE_PR_HOST_SUFFIX }}/digital-trust/showcase" target="_blank" rel="noopener noreferrer">https://pr-${{ github.event.pull_request.number }}-${{ env.SHOWCASE_PR_HOST_SUFFIX }}/digital-trust/showcase</a> |
Showcase PR deployment URL (Helm release `pr-${{ github.event.pull_request.number }}-showcase`).