Skip to content

Commit 4109502

Browse files
author
billy clark
authored
Merge pull request #1092 from sillsdev/staging
Merge staging into master for production build/deploy flow testing purposes
2 parents e790524 + d3039a5 commit 4109502

27 files changed

+801
-447
lines changed

.github/workflows/build-and-deploy-images.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@ jobs:
5555
echo "BUILD_VERSION=$(echo ${GITHUB_REF:11})" >> "$GITHUB_ENV"
5656
echo "BUILD_VERSION_LATEST=latest" >> "$GITHUB_ENV"
5757
58-
- name: Log in to Docker Hub
59-
uses: docker/login-action@v1
60-
with:
61-
username: ${{ secrets.DOCKERHUB_USERNAME }}
62-
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
63-
6458
- name: Build and tag app
6559
run: docker build -t $IMAGE_NAME:$BUILD_VERSION -t $IMAGE_NAME:$BUILD_VERSION_LATEST --build-arg BUILD_VERSION=${BUILD_VERSION} -f docker/app/Dockerfile .
6660
env:
@@ -69,6 +63,12 @@ jobs:
6963
- name: Reveal images
7064
run: docker images
7165

66+
- name: Log in to Docker Hub
67+
uses: docker/login-action@v1
68+
with:
69+
username: ${{ secrets.DOCKERHUB_USERNAME }}
70+
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
71+
7272
- name: Publish all tagged images to Docker Hub
7373
run: |
7474
docker push -a sillsdev/web-languageforge

README.md

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,6 @@ If you edit files in the `src` or `data` folders of the test container, these ch
143143

144144
After a minute or two, your source or test changes should be applied and you should see the result of your changes when you run the E2E tests again.
145145

146-
### Viewing logs
147-
148-
1. `make logs` will show logs from any running containers, results can be filtered by simply grepping, e.g., `make logs | grep lf-ui-builder`
149-
150146
### Cleanup
151147

152148
1. `make clean` is the most common, it shuts down and cleans up running containers
@@ -157,9 +153,9 @@ After a minute or two, your source or test changes should be applied and you sho
157153

158154
1. `make dev` will start the app in development mode, i.e. changes to source code will immediately be reflected in the locally running app.
159155

160-
### Building for production
156+
### Building for deployment
161157

162-
1. `make prod` will build a production version of the app.
158+
1. Refer to `/.github/workflows/build-and-deploy-images.yml` for build commands.
163159

164160
### Visual Studio Code ###
165161

@@ -228,25 +224,35 @@ To debug the tests:
228224
- To debug in VSCode, select the "Node debugger" debug configuration and run it.
229225

230226
## Application deployment ##
231-
Language Forge is built to run in a containerized environment. For now, Kubernetes is the chosen runtime platform.
227+
Language Forge is built to run in a containerized environment. For now, Kubernetes is the chosen runtime platform. Deployments are not currently automated and must be manually run with the appropriate credentials or from within our CD platform, TeamCity at this time. Deployment scripts for k8s can be found in `docker/deployment`
232228

233229
### Staging (QA) ###
234-
Deployments are not currently automated and must be manually run with the appropriate credentials or from within our CD platform, TeamCity at this time.
235-
236-
Deployment scripts for k8s can be found in `docker/deployment` and staging deployments can be run via `VERSION=<some-docker-tag-or-semver> make deploy-staging` from within the same directory.
230+
Staging deployments can be run with `VERSION=<some-docker-tag-or-semver> make deploy-staging`.
237231

238232
Current workflow:
239-
1. move the `staging` branch to the appropriate commit on `master`
233+
1. merge commits into or make commits on `staging` branch
240234
1. this will kick off the GHA (`.github/workflows/build-and-deploy-images.yml`) to build and publish the necessary images to Docker Hub (https://hub.docker.com/r/sillsdev/web-languageforge/tags)
241235
1. then the deployment scripts can be run either manually or via the TeamCity deploy job
242236

243237
### Production ###
244-
WIP: `docker/deployment/Makefile` currently has a `VERSION=<some-docker-tag-or-semver> make deploy-prod` that can be run locally with the right cluster credenitals.
238+
Production deployments can be run with `VERSION=<some-docker-tag-or-semver> make deploy-prod`.
239+
240+
Current workflow:
241+
1. merge from `staging` into `master`
242+
1. tag the desired commit on `master` with a `v#.#.#` format and push the tag
243+
1. this will kick off the GHA (`.github/workflows/build-and-deploy-images.yml`) to build and publish the necessary images to Docker Hub (https://hub.docker.com/r/sillsdev/web-languageforge/tags)
244+
1. then the deployment scripts can be run either manually or via the TeamCity deploy job
245245

246-
- [ ] build prod images
247-
- [ ] publish prod images via GHA workflow
248-
- [x] parameterize image reference in `app-deployment.yaml`
249-
- [ ] set up CD for prod
246+
### Backup/Restore ###
247+
Backups will be established automatically by LTOps and utilized by LF through the `storageClassName` property in a Persistent Volume Claim. This storage class provided by LTOps establishes both a frequency and retention for a backup. Any time a restoration is needed, the LF team will need to coordinate the effort with LTOps. The process of restoring from a point in time will require the application be brought down for maintenance. The process will roughly follow these steps:
248+
1. Notify LTOps of the need to restore a backup (App team)
249+
1. Coordinate a time to bring the app down for maintenance (LTOps/App team)
250+
1. Scale the app down (LTOps/App team)
251+
1. Initiate the Backup restore (LTOps)
252+
1. Notify app team of the restoration completion (LTOps)
253+
1. Scale the app up (LTOps/App team)
254+
1. Test the app (App team)
255+
1. Communicate maintenance completion
250256

251257
## Libraries Used ##
252258

docker/Makefile

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,6 @@ endif
3737
build:
3838
docker-compose build mail app ld-api
3939

40-
.PHONY: deployable-app
41-
deployable-app:
42-
docker-compose build --build-arg BUILD_VERSION=${BUILD_VERSION} app
43-
44-
.PHONY: logs
45-
logs:
46-
docker-compose logs
47-
4840
.PHONY: clean
4941
clean:
5042
docker-compose down

docker/app/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# ENVIRONMENT value can be either "production" or "development"
2-
ARG ENVIRONMENT=production
2+
ARG ENVIRONMENT=${ENVIRONMENT:-'production'}
33

44
# UI-BUILDER
55
FROM node:14.16.1-alpine3.11 AS ui-builder-base

docker/app/entrypoint.sh

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
11
#!/bin/sh
22

3-
if [ "x$ENVIRONMENT" = "xdevelopment" ]; then
4-
/wait
5-
RETCODE=$?
6-
if [ "$RETCODE" -gt 0 ]; then
7-
exit $RETCODE
8-
fi
9-
fi
10-
113
# rsyslog needs to run so that lfmerge can log to /var/log/syslog
124
/etc/init.d/rsyslog start
135

146
# run lfmergeqm on startup to clear out any failed send/receive sessions from previous container
15-
if which /lfmergeqm-background.sh > /dev/null
16-
then
17-
# MUST be run as a background process as it kicks off an infinite loop to run every 24 hours
18-
/lfmergeqm-background.sh &
19-
fi
7+
/lfmergeqm-background.sh & # MUST be run as a background process as it kicks off an infinite loop to run every 24 hours
208

219
# Now chain to Docker entrypoint from base php:apache image
2210
exec docker-php-entrypoint "$@"

docker/deployment/Makefile

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,13 @@ deploy-staging: deploy-db deploy-mail-staging deploy-app-staging
2828
deploy-mail-staging:
2929
sed -e s/{{SERVER_HOSTNAME}}/qa.languageforge.org/ mail-deployment.yaml | kubectl apply -f -
3030
deploy-app-staging:
31-
sed -e s/{{ENVIRONMENT}}/development/ app-deployment.yaml \
32-
| sed -e s/{{WEBSITE}}/qa.languageforge.org/ \
31+
sed -e s/{{WEBSITE}}/qa.languageforge.org/ app-deployment.yaml \
3332
| sed -e s/{{VERSION}}/$(VERSION)/ | kubectl apply -f -
3433
deploy-prod: deploy-db deploy-mail-prod deploy-app-prod
3534
deploy-mail-prod:
3635
sed -e s/{{SERVER_HOSTNAME}}/beta.languageforge.org/ mail-deployment.yaml | kubectl apply -f -
3736
deploy-app-prod:
38-
sed -e s/{{ENVIRONMENT}}/production/ app-deployment.yaml \
39-
| sed -e s/{{WEBSITE}}/beta.languageforge.org/ \
37+
sed -e s/{{WEBSITE}}/beta.languageforge.org/ app-deployment.yaml \
4038
| sed -e s/{{VERSION}}/$(VERSION)/ | kubectl apply -f -
4139
deploy-db:
4240
kubectl apply -f db-deployment.yaml

docker/deployment/app-deployment.yaml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ apiVersion: networking.k8s.io/v1
2222
kind: Ingress
2323
metadata:
2424
name: languageforge-app
25+
annotations:
26+
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#custom-max-body-size
27+
# Added this to allow large file uploads, this setting should match the php custom config, i.e., upload_max_filesize, found in the app's customizations.php.ini
28+
nginx.ingress.kubernetes.io/proxy-body-size: 60M
2529
spec:
2630
rules:
2731
- host: {{WEBSITE}}
@@ -51,7 +55,7 @@ spec:
5155
- ReadWriteMany
5256
resources:
5357
requests:
54-
storage: 7Gi
58+
storage: 10Gi
5559
storageClassName: weekly-snapshots-retain-4 # provided by LTOps
5660

5761
---
@@ -66,7 +70,7 @@ spec:
6670
- ReadWriteMany
6771
resources:
6872
requests:
69-
storage: 10Gi
73+
storage: 35Gi
7074
storageClassName: weekly-snapshots-retain-4 # provided by LTOps
7175

7276
---
@@ -122,7 +126,7 @@ spec:
122126
- name: DATABASE
123127
value: scriptureforge
124128
- name: ENVIRONMENT
125-
value: {{ENVIRONMENT}}
129+
value: production
126130
- name: WEBSITE
127131
value: {{WEBSITE}}
128132
- name: MAIL_HOST

docker/deployment/db-deployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ spec:
2323
- ReadWriteOnce
2424
resources:
2525
requests:
26-
storage: 3Gi
26+
storage: 10Gi
2727
storageClassName: weekly-snapshots-retain-4 # provided by LTOps
2828

2929
---

docker/deployment/scripts/kubeRsyncAssets.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
# -p 55555 this port is being forwarded to 22 on the container
66
# -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" these are a hack to bypass security checks for "localhost". localhost isn't a real host so I don't care about "host key verification failed" errors when doing localhost port forwarding
77

8-
ssh -A -p 55555 -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" root@localhost "rsync -avzhP [email protected]:/var/www/languageforge.org/htdocs/assets/lexicon/ /var/www/html/assets/lexicon/"
8+
USERANDHOSTNAME=user@hostname
9+
10+
ssh -A -p 55555 -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" root@localhost "rsync -avzhP $USERANDHOSTNAME:/var/www/languageforge.org/htdocs/assets/lexicon/ /var/www/html/assets/lexicon/"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/bash
2+
3+
echo Mongo Dump
4+
ssh mongo-xf mongodump
5+
6+
echo Remove Scripture Forge data from dump
7+
ssh mongo-xf rm -r dump/xforge
8+
9+
echo Create tar file of dump
10+
ssh mongo-xf tar -czvf mongodump.tgz dump
11+
12+
echo Copy tar file to local filesystem
13+
scp mongo-xf:mongodump.tgz .
14+
15+
echo Clean up on remote
16+
ssh mongo-xf rm -r dump
17+
ssh mongo-xf rm mongodump.tgz
18+
19+
MONGOPOD=$(kubectl get pods --selector='app=db' -o name | sed -e s'/pod\///')
20+
21+
echo Copying mongodump.tgz into $MONGOPOD/data/db
22+
kubectl cp -c db mongodump.tgz $MONGOPOD:/data/db
23+
24+
echo Untarring mongodump.tgz
25+
kubectl exec -c db $MONGOPOD -- bash -c "cd /data/db \
26+
&& tar -xvzf mongodump.tgz"
27+
28+
echo MongoRestore
29+
kubectl exec -c db $MONGOPOD -- bash -c "cd /data/db \
30+
&& mongorestore --drop dump"
31+
32+
echo Clean Up
33+
kubectl exec -c db $MONGOPOD -- bash -c "rm -r /data/db/dump && rm /data/db/mongodump.tgz"
34+
rm mongodump.tgz
35+
36+
echo Run Mongo migration
37+
kubectl exec -c db $MONGOPOD -- bash -c 'mongo scriptureforge --eval "db.projects.updateMany({}, {"\$unset": {userProperties: 1}});"'
Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
#!/bin/bash
22
MONGO=deploy/db
3-
POD=$(kubectl get pods --selector='app=app' -o name | sed -e s'/pod\///')
3+
APPPOD=$(kubectl get pods --selector='app=app' -o name | sed -e s'/pod\///')
4+
MONGOPOD=$(kubectl get pods --selector='app=db' -o name | sed -e s'/pod\///')
45

56
# install SSH and rsync; also start the SSH service
6-
echo Installing SSH on pod $POD
7-
kubectl exec -c app $POD -- bash -c "apt-get update \
7+
echo Installing SSH on pod $APPPOD
8+
kubectl exec -c app $APPPOD -- bash -c "apt-get update \
89
&& apt-get install -y openssh-server openssh-client rsync \
910
&& mkdir -p -m 700 /root/.ssh \
1011
&& service ssh start"
1112

1213
# add my public key to the container so I can "ssh root@localhost"
1314
# --no-preserve=true keeps the permissions intact for root on the container side
14-
kubectl cp -c app ~/.ssh/authorized_keys $POD:/root/.ssh/authorized_keys --no-preserve=true
15+
kubectl cp -c app ~/.ssh/authorized_keys $APPPOD:/root/.ssh/authorized_keys --no-preserve=true
16+
17+
echo Installing SSH on pod $MONGOPOD
18+
kubectl exec -c db $MONGOPOD -- bash -c "apt-get update \
19+
&& apt-get install -y openssh-server openssh-client rsync \
20+
&& mkdir -p -m 700 /root/.ssh \
21+
&& service ssh start"
22+
23+
# add my public key to the container so I can "ssh root@localhost"
24+
# --no-preserve=true keeps the permissions intact for root on the container side
25+
kubectl cp -c db ~/.ssh/authorized_keys $MONGOPOD:/root/.ssh/authorized_keys --no-preserve=true

docker/docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ services:
4949
- FACEBOOK_CLIENT_SECRET=bogus-development-token
5050
- REMEMBER_ME_SECRET=bogus-development-key
5151
- LANGUAGE_DEPOT_API_TOKEN=bogus-development-token
52+
command: sh -c "/wait && apache2-foreground"
5253
extra_hosts:
5354
- "host.docker.internal:host-gateway"
5455
volumes:

docker/test-e2e/Dockerfile

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
# ENVIRONMENT value can be either "production" or "development"
2-
ARG ENVIRONMENT=development
3-
41
# UI-BUILDER
5-
FROM node:14.16.1-alpine3.11 AS ui-builder-base
2+
FROM node:14.16.1-alpine3.11
63

74
# install npm globally
85
RUN npm config set unsafe-perm true && npm install -g [email protected]
@@ -28,15 +25,8 @@ COPY src/sass ./src/sass
2825
COPY src/service-worker ./src/service-worker
2926
COPY src/Site/views ./src/Site/views
3027

31-
FROM ui-builder-base AS production-ui-builder
32-
ENV NPM_BUILD_SUFFIX=prd
33-
34-
FROM ui-builder-base AS development-ui-builder
35-
ENV NPM_BUILD_SUFFIX=dev
36-
37-
FROM ${ENVIRONMENT}-ui-builder AS ui-builder
3828
# artifacts built to /data/src/dist
39-
RUN npm run build:${NPM_BUILD_SUFFIX}
29+
RUN npm run build:dev
4030

4131
# make wait available for container ochestration
4232
COPY --from=sillsdev/web-languageforge:wait-latest /wait /wait

0 commit comments

Comments
 (0)