Skip to content

Commit 5a57f96

Browse files
committed
feat: add Docker & Jenkins support with build and push scripts, environment variable handling, and endpoint configuration
1 parent fe1c0ae commit 5a57f96

16 files changed

Lines changed: 301 additions & 46 deletions

File tree

.dockerignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
node_modules
22
build
33
.git
4+
deploy/Dockerfile
5+
deploy/build.sh
6+
deploy/push.sh
7+
Jenkinsfile

.env-example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
# docker run ... --env-file .env ...
33
WS_URL=ws://localhost:9944
44
POLKADOT_UI_SAMPLE=42
5+
APP_NAME=Polymesh Staging
6+
UI_COLOR=
7+
RPC_HOSTNAME=staging-rpc.polymesh.live

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @quinndiggitypolymath @F-OBrien @Neopallium @mpastecki

Jenkinsfile

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////
2+
3+
def withSecretEnv(List<Map> varAndPasswordList, Closure closure) {
4+
wrap([$class: 'MaskPasswordsBuildWrapper', varPasswordPairs: varAndPasswordList]) {
5+
withEnv(varAndPasswordList.collect { "${it.var}=${it.password}" }) {
6+
closure()
7+
}
8+
}
9+
}
10+
11+
//////////////////////////////////////////////////////////////////////////////////////////
12+
13+
node {
14+
15+
env.PROJECT_NAME = 'polymesh-apps'
16+
env.GIT_REPO = "ssh://git@ssh.gitea.polymesh.dev:4444/Deployment/${PROJECT_NAME}.git"
17+
18+
properties([[$class: 'BuildDiscarderProperty',
19+
strategy: [$class: 'LogRotator',
20+
numToKeepStr: '7',
21+
daysToKeepStr: '7',
22+
artifactNumToKeepStr: '7',
23+
artifactDaysToKeepStr: '7']]])
24+
25+
if (env.CHANGE_BRANCH) {
26+
env.GIT_BRANCH = env.CHANGE_BRANCH // Job was started from a pull request
27+
} else {
28+
env.GIT_BRANCH = env.BRANCH_NAME
29+
}
30+
31+
dir("${JENKINS_HOME}/workspace/${JOB_NAME}/${BUILD_NUMBER}") {
32+
33+
withCredentials([
34+
usernamePassword(credentialsId: 'vault_approle',
35+
usernameVariable: 'VAULT_ROLE_ID',
36+
passwordVariable: 'VAULT_SECRET_ID'),
37+
]) {
38+
39+
env.VAULT_ADDR = 'https://127.0.0.1:8200/'
40+
env.VAULT_CACERT = '/etc/ssl/certs/vault.tls.chain.pem'
41+
42+
withSecretEnv([[var: 'VAULT_TOKEN',
43+
password: sh (returnStdout: true,
44+
label: 'Login To Vault',
45+
script: '''\
46+
vault write -field=token \
47+
-format=table \
48+
auth/approle/login \
49+
role_id="$VAULT_ROLE_ID" \
50+
secret_id="$VAULT_SECRET_ID"
51+
'''.stripIndent()).trim()]]) {
52+
stage('Clone Repo') {
53+
sh (label: 'Clone Repo',
54+
script: '/usr/local/bin/gitea-clone-repo.sh')
55+
}
56+
}
57+
}
58+
59+
dir("${PROJECT_NAME}") {
60+
61+
env.GIT_COMMIT = sh (returnStdout: true,
62+
label: 'Read Git Commit',
63+
script: 'git rev-parse HEAD').trim()
64+
65+
echo "GIT_COMMIT: ${env.GIT_COMMIT}"
66+
67+
stage('Build') {
68+
sh (label: 'Run `./deploy/build.sh`',
69+
script: './deploy/build.sh')
70+
}
71+
72+
stage('Push') {
73+
sh (label: 'Run `./deploy/push.sh`',
74+
script: './deploy/push.sh')
75+
}
76+
77+
}
78+
}
79+
}
80+
81+
//////////////////////////////////////////////////////////////////////////////////////////

deploy/Dockerfile

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
################################################################
2+
3+
ARG NODE_VERSION=22
4+
ARG DEBIAN_VERSION=bookworm
5+
ARG NODE_CONTAINER_TAG=${NODE_VERSION}-${DEBIAN_VERSION}-slim
6+
7+
################################################################
8+
9+
FROM node:${NODE_CONTAINER_TAG} as builder
10+
11+
################################################################
12+
13+
USER root
14+
RUN npm i -g npm
15+
16+
################################################################
17+
18+
# Install any needed packages
19+
RUN apt-get update && \
20+
apt-get install --no-install-recommends -y curl git gnupg ca-certificates python3 pkg-config make cmake g++ libudev-dev libusb-1.0-0-dev
21+
22+
################################################################
23+
24+
WORKDIR /apps
25+
26+
COPY --chown=node:node . .
27+
28+
RUN chown -R node: /apps
29+
30+
RUN sed -n 's/^\(.*\)=.*$/\1=__\1__/p' .env-example > .env.production.local && \
31+
cat .env.production.local | \
32+
xargs -I{} bash -c "echo '{}' | sed 's/^\\(.*\\)=.*$/\\1/' >> /srv/env.var.list"
33+
34+
USER node
35+
36+
RUN yarn && NODE_ENV=production yarn build:www
37+
38+
################################################################
39+
40+
FROM nginx:stable-alpine
41+
42+
# The following is mainly for doc purpose to show which ENV is supported
43+
ENV WS_URL=
44+
45+
WORKDIR /usr/share/nginx/html
46+
47+
COPY docker/env.sh .
48+
49+
RUN apk add --no-cache bash; chmod +x env.sh
50+
51+
COPY docker/nginx.conf /etc/nginx/nginx.conf
52+
COPY --from=builder /apps/packages/apps/build /usr/share/nginx/html
53+
COPY --from=builder /srv/env.var.list /srv/env.var.list
54+
COPY --chown=root:root deploy/replace-env-var-placeholders.sh /usr/local/bin/replace-env-var-placeholders.sh
55+
56+
ENV APP_NAME=APP_NAME_NOT_SET
57+
ENV RPC_HOSTNAME=RPC_HOSTNAME_NOT_SET
58+
ENV WS_URL=WS_URL_NOT_SET
59+
ENV POLKADOT_UI_SAMPLE=POLKADOT_UI_SAMPLE_NOT_SET
60+
ENV UI_COLOR=UI_COLOR_NOT_SET
61+
62+
EXPOSE 80
63+
64+
CMD replace-env-var-placeholders.sh && \
65+
/usr/share/nginx/html/env.sh && \
66+
nginx -g 'daemon off;'
67+
68+
################################################################

deploy/build.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
#!/bin/bash
3+
4+
set -exu -o pipefail
5+
6+
: "${AWS_REGION:=us-west-2}"
7+
: "${CONTAINER_REGISTRY:=201135299591.dkr.ecr.${AWS_REGION}.amazonaws.com}"
8+
: "${CONTAINER_TAG:=$(git rev-parse HEAD)}"
9+
10+
export CONTAINER_TAG
11+
12+
docker build -f deploy/Dockerfile -t "${CONTAINER_REGISTRY}/polymesh/app-ui:${CONTAINER_TAG}" .

deploy/env.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
# Copyright 2017-2025 @polkadot/apps authors & contributors
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# This script is used when the docker container starts and does the magic to
6+
# bring the ENV variables to the generated static UI.
7+
8+
TARGET=./env-config.js
9+
10+
# Recreate config file
11+
echo -n > $TARGET
12+
13+
declare -a vars=(
14+
"WS_URL"
15+
"SAMPLE"
16+
)
17+
18+
echo "window.process_env = {" >> $TARGET
19+
for VAR in ${vars[@]}; do
20+
echo " $VAR: \"${!VAR}\"," >> $TARGET
21+
done
22+
echo "}" >> $TARGET

deploy/push.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
set -exu -o pipefail
4+
5+
: "${AWS_PROFILE:=polymesh_primary}"
6+
: "${AWS_REGION:=us-west-2}"
7+
: "${CONTAINER_REGISTRY:=201135299591.dkr.ecr.${AWS_REGION}.amazonaws.com}"
8+
: "${CONTAINER_TAG:=$(git rev-parse HEAD)}"
9+
10+
export AWS_REGION
11+
export AWS_DEFAULT_REGION=$AWS_REGION
12+
13+
if [[ $(whoami) != "jenkins" ]]; then
14+
export AWS_PROFILE=$AWS_PROFILE
15+
fi
16+
17+
aws ecr get-login-password | \
18+
docker login "$CONTAINER_REGISTRY" --username AWS --password-stdin
19+
20+
docker push "${CONTAINER_REGISTRY}/polymesh/app-ui:${CONTAINER_TAG}" || true # temporary workaround for "... image tag already exists... and cannot be overwritten because the repository is immutable."
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
set -exuk -o pipefail
4+
5+
date
6+
echo "Replacing environment variable placeholders..."
7+
8+
cat /srv/env.var.list | \
9+
xargs -I{} bash -c "grep -rl '__{}__' /usr/share/nginx/html | xargs --no-run-if-empty sed -i 's/__{}__/\${{}}/g'"
10+
11+
date
12+
echo "Finished replacing environment variable placeholders"
13+
14+
date
15+
echo "Replacing environment variables with their runtime values..."
16+
17+
while read LINE; do
18+
TMP=$(mktemp)
19+
chmod 0644 "$TMP"
20+
chown root:root "$TMP"
21+
grep -rl "\${$LINE}" /usr/share/nginx/html | \
22+
xargs --no-run-if-empty -I{} bash -c "envsubst '\${$LINE}' < '{}' > '$TMP' && mv '$TMP' '{}'" || true
23+
done < /srv/env.var.list
24+
25+
date
26+
echo "Finished replacing environment variables with their runtime values"

packages/apps-config/src/endpoints/chains.ts

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,21 @@ import type { EndpointOption } from './types.js';
55

66
import { nodesPolymeshSVG } from '../ui/logos/nodes/index.js';
77

8-
/* eslint-disable sort-keys */
9-
108
// The available endpoints that will show in the dropdown. For the most part (with the exception of
119
// Polkadot) we try to keep this to live chains only, with RPCs hosted by the community/chain vendor
1210
// info: The chain logo name as defined in ../ui/logos/index.ts in namedLogos (this also needs to align with @polkadot/networks)
1311
// text: The text to display on the dropdown
1412
// providers: The actual hosted secure websocket endpoint
1513
//
16-
// IMPORTANT: Alphabetical based on text
17-
export const chains: EndpointOption[] = [
18-
19-
// {
20-
// info: 'polymesh',
21-
// text: '__APP_NAME__',
22-
// providers: {
23-
// Polymesh: 'wss://__RPC_HOSTNAME__/'
24-
// },
25-
// ui: {
26-
// color: '__UI_COLOR__',
27-
// logo: nodesPolymeshSVG
28-
// }
29-
// },
30-
{
31-
info: 'polymesh',
32-
providers: {
33-
Polymesh: 'wss://testnet-rpc.polymesh.live'
34-
},
35-
text: 'Polymesh Testnet',
36-
ui: {
37-
color: '#43195B',
38-
logo: nodesPolymeshSVG
39-
}
14+
// IMPORTANT: This is the deployment-specific endpoint configured via environment variables
15+
export const deploymentChain: EndpointOption = {
16+
info: 'polymesh',
17+
providers: {
18+
Polymesh: 'wss://__RPC_HOSTNAME__/'
19+
},
20+
text: '__APP_NAME__',
21+
ui: {
22+
color: '__UI_COLOR__',
23+
logo: nodesPolymeshSVG
4024
}
41-
];
25+
};

0 commit comments

Comments
 (0)