Skip to content

Commit 8654bde

Browse files
author
Diego Guerrero Carrasco
committed
Improved DevOps: new GitHub Actions CI/CD system and refined Docker and server-frontend integration
Numerous modifications have been made to improve the deployment of VSCode4Teaching and adapt it to the presence of the new web application: - Changed system for continuous integration, deployment and delivery (CI/CD), moving away from using Travis CI to start using GitHub Actions. For this, two workflows have been defined: one for the extension and one for the server & Angular web application. Specific documentation about the new system is introduced in the .github/workflows folder. - The Dockerfile, docker-compose.yml and .env files have been modified and moved to the root of the project, since they affect two of the three components. In addition, the versions of the images used for the compilation in the Dockerfile have been updated and the deployment using Compose has been updated for v2. - The .dockerignore files for each component have been removed to introduce a single description in the project root. - The server has been modified to introduce a new request interceptor that, before resolving the routing in the framework, decides if the received path should be handled by the web application (redirecting the request to índex.html) or if it should be resolved in the framework. This allows a better integration of the compiled Angular framework as a static resource in the application and, thus, the presence of the /app path to access all Angular resources can be eliminated.
1 parent 85f46cf commit 8654bde

File tree

20 files changed

+367
-170
lines changed

20 files changed

+367
-170
lines changed

.dockerignore

+43-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,43 @@
1-
.git
1+
# Ignore VSCode4Teaching unnecesary directories
2+
**/v4t-course/
3+
4+
# Ignore Maven build directories
5+
**/target/
6+
**/logs/
7+
**/tmp/
8+
9+
# Ignore Node/Angular build directories and dependencies
10+
**/node_modules/
11+
**/dist/
12+
**/.angular/
13+
**/.cache/
14+
15+
# Ignore IDE specific directories and files
16+
**/.vscode/
17+
**/.idea/
18+
**/.project
19+
**/.classpath
20+
21+
# Ignore documentation files
22+
**/*.md
23+
24+
# Ignore MacOS specific files
25+
**/.DS_Store
26+
**/.AppleDouble
27+
**/.LSOverride
28+
29+
# Ignore other unnecesary system files
30+
**/Thumbs.db
31+
**/ehthumbs.db
32+
**/Desktop.ini
33+
**/$RECYCLE.BIN/
34+
35+
# Ignore git files
36+
**/.git/
37+
**/.gitignore
38+
39+
# Ignore Dockerfile and Dockerignore themselves
40+
**/docker-compose.yml
41+
**/compose.yml
42+
**/Dockerfile
43+
**/.dockerignore
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
SERVER_PORT=8080
2+
23
MYSQL_ROOT_PASSWORD=T4cwGK3q5NdR3vMz
34
MYSQL_DATABASE=vscode4teach
5+
46
SPRING_DATASOURCE_USERNAME=vscode4teach
57
SPRING_DATASOURCE_PASSWORD=AvScnGQp5e4GHnd
68
SPRING_DATASOURCE_URL=jdbc:mysql://db/vscode4teach?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
9+
710
JWT_SECRET=vscode4teaching
11+
812
V4T_FILEDIRECTORY=/app/v4t_courses
13+
914
FILE_INITIALIZATION=false
1015
DATA_INITIALIZATION=false
1116
SPRING_JPA_HIBERNATE_DDL_AUTO=create-drop
17+
1218
SUPERUSER_USERNAME=admin
13-
SUPERUSER_PASSWORD=admin
19+
SUPERUSER_PASSWORD=adminpassword
1420
SUPERUSER_EMAIL=admin@admin.com
1521
SUPERUSER_NAME=Admin
1622
SUPERUSER_LASTNAME=Admin

.github/workflows/README.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# VSCode4Teaching
2+
**Developer documentation on the Continuous Integration, Delivery and Deployment (*CI/CD*) system of this project**
3+
4+
This project is configured with a continuous integration, deployment and delivery system through [GitHub Actions](https://github.com/features/actions). This system comprises two *workflows*: one for the extension (file [`extension.ci.yml`](extension.ci.yml)) and one for the server and web application (file [`server.ci.yml`](server.ci.yml)).
5+
6+
### Detailed description of declared jobs
7+
The aforementioned files define the jobs that will be executed sequentially based on the type of changes registered in the repository. These jobs are:
8+
- `test`. This job runs when changes are pushed to the `master` (or `main`) and `develop` branches or when a *pull request* is opened targeting any of these branches. After setting up the execution environment on the pipeline runner, it executes the complete test suite implemented in the component on which the pipeline is launched, returning success if the tests pass.
9+
- `publish`. This job runs when a change is made to the `master` branch, meaning a new version of VSCode4Teaching is being released. This step requires the deployed version to be correctly configured in each component's manifest, which are POM (`pom.xml`) for the server, and `package.json` for both the extension and web application.
10+
- For the extension, this job will compile and package the extension source code into VSIX format and deploy it to the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/VSCode) in its new version. This job will fail if a version with the same identifier has already been deployed previously or if the authentication token has expired or is invalid for publishing.
11+
- For the server, it will execute a Docker image build process defined through the `Dockerfile` file, which is *multistage*: it will build the web application in a first Node container to produce the static files (HTML, CSS, JS) needed to run the application without Node, compile the server source code along with the frontend static resources in a second Maven container with JDK 11, and use a third container to define the final image on JDK 11, setting the *entrypoint* command to run the JAR obtained in the previous stage. The resulting image is tagged with the version declared in the POM and also as `latest`. Both images are pushed to the specified [Docker Hub](https://hub.docker.com) repository.
12+
- `deploy`. Executed only under the same conditions as `publish`, and declared just in the server workflow, this job allows deploying the built Docker image to the defined production server. It connects via SSH to the remote computer, copies the `docker-compose.yml` file, pulls the new image generated in the previous job and restarts the Docker Compose instance running the configured production server.
13+
14+
### Parameterized definition of variables and secrets
15+
To run the previously explained jobs, certain variables and secrets must be properly defined in the repository:
16+
- Publishing the server image to Docker Hub. These variables are used during the server (embedding the built web application) image publishing to Docker Hub and subsequent production deployment.
17+
- `DOCKER_HUB_USERNAME` (variable). The username used to create the Docker image for the VSCode4Teaching server (and web application as static frontend resource). It will be the first part of the image name (preceding the `/`) and must match the name specified in the `docker-compose.yml` file to ensure successful production deployment.
18+
- `DOCKER_HUB_IMAGE_NAME` (variable). Properly, the name of the image (following the `/` that separates it from the username). It must match the name used in the Docker Compose definition to complete the deployment job correctly.
19+
- `DOCKER_HUB_PAT` (secret). The personal access token required to publish the built image to Docker Hub. If it is incorrect or invalid, the pipeline execution will fail.
20+
- Deploying on the production server. These variables are used to access the remote computer that hosts the production server.
21+
- `EDUKAFORA_HOST` (variable). The address to which the pipeline executor will connect via SSH during deployment through the default port (22).
22+
- `EDUKAFORA_USER` (variable). The user hosting the VSCode4Teaching project on the production machine.
23+
- `EDUKAFORA_SSH_KEY` (secret). The private key used to authenticate the SSH connection.
24+
- `EDUKAFORA_PATH` (variable). The path, preferably absolute, on the production environment where the existing deployment is located and will be replaced.
25+
- Publishing the extension to the Visual Studio Code Marketplace. This variable is used in the extension workflow for publishing new versions.
26+
- `VSCODE_MARKETPLACE_PAT` (secret). The personal access token required to authenticate the publication to the Visual Studio Code Marketplace. It has a scheduled expiration, so it may need to be replaced or renewed if an error occurs during the pipeline execution. The definition of the extension name, publisher, and other deployment and publication details are contained in its `package.json`, and the configured token must be able to authenticate and published according to the parameters set in the manifest file.

.github/workflows/extension.ci.yml

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: "Extension pipeline"
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- main
8+
- develop
9+
pull_request:
10+
branches:
11+
- master
12+
- main
13+
- develop
14+
15+
jobs:
16+
test:
17+
runs-on: ubuntu-latest
18+
defaults:
19+
run:
20+
working-directory: ./vscode4teaching-extension
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
with:
25+
ref: ${{ github.ref }}
26+
- name: Set up Node version
27+
uses: actions/setup-node@v4
28+
with:
29+
node-version: 18
30+
- name: Install dependencies
31+
run: npm ci
32+
- name: Build
33+
run: npm run build
34+
- name: Test
35+
run: npm run test
36+
publish:
37+
runs-on: ubuntu-latest
38+
defaults:
39+
run:
40+
working-directory: ./vscode4teaching-extension
41+
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') }}
42+
needs: test
43+
steps:
44+
- name: Checkout repository
45+
uses: actions/checkout@v4
46+
with:
47+
ref: ${{ github.ref }}
48+
- name: Set up Node version
49+
uses: actions/setup-node@v4
50+
with:
51+
node-version: 18
52+
- name: Install dependencies and VSCode extension manager (vsce)
53+
run: npm ci && npm install -g @vscode/vsce
54+
- name: Check VSCode Marketplace token validity
55+
run: npx vsce verify-pat
56+
env:
57+
VSCE_PAT: ${{ secrets.VSCODE_MARKETPLACE_PAT }}
58+
- name: Publish to VSCode Marketplace
59+
run: npx vsce publish --allow-star-activation
60+
env:
61+
VSCE_PAT: ${{ secrets.VSCODE_MARKETPLACE_PAT }}

.github/workflows/server.ci.yml

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: "Server pipeline"
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- main
8+
- develop
9+
pull_request:
10+
branches:
11+
- master
12+
- main
13+
- develop
14+
15+
jobs:
16+
test:
17+
runs-on: ubuntu-latest
18+
defaults:
19+
run:
20+
working-directory: ./vscode4teaching-server
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
- name: Set up Java version
25+
uses: actions/setup-java@v4
26+
with:
27+
java-version: 11
28+
distribution: temurin
29+
- name: Test
30+
run: ./mvnw clean dependency:resolve test
31+
publish:
32+
runs-on: ubuntu-latest
33+
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') }}
34+
needs: test
35+
steps:
36+
- name: Checkout repository
37+
uses: actions/checkout@v4
38+
with:
39+
ref: ${{ github.ref }}
40+
- name: Get deployed version from POM
41+
run: |
42+
VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
43+
echo VERSION=$VERSION >> $GITHUB_ENV
44+
working-directory: ./vscode4teaching-server
45+
- name: Build Docker image
46+
run: |
47+
env | grep DOCKER
48+
DOCKER_IMAGE="$DOCKER_HUB_USERNAME/$DOCKER_HUB_IMAGE_NAME"
49+
echo DOCKER_IMAGE=$DOCKER_IMAGE >> $GITHUB_ENV
50+
docker build -t $DOCKER_IMAGE:$VERSION -t $DOCKER_IMAGE:latest .
51+
env:
52+
DOCKER_HUB_USERNAME: ${{ vars.DOCKER_HUB_USERNAME }}
53+
DOCKER_HUB_IMAGE_NAME: ${{ vars.DOCKER_HUB_IMAGE_NAME }}
54+
VERSION: ${{ env.VERSION }}
55+
- name: Push to Docker Hub
56+
run: |
57+
echo $DOCKER_HUB_PAT | docker login -u $DOCKER_HUB_USERNAME --password-stdin
58+
docker push $DOCKER_IMAGE:$VERSION
59+
docker push $DOCKER_IMAGE:latest
60+
env:
61+
DOCKER_HUB_USERNAME: ${{ vars.DOCKER_HUB_USERNAME }}
62+
DOCKER_IMAGE: ${{ env.DOCKER_IMAGE }}
63+
VERSION: ${{ env.VERSION }}
64+
DOCKER_HUB_PAT: ${{ secrets.DOCKER_HUB_PAT }}
65+
66+
deploy:
67+
runs-on: ubuntu-latest
68+
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main') }}
69+
needs: publish
70+
steps:
71+
- name: Checkout repository
72+
uses: actions/checkout@v4
73+
with:
74+
ref: ${{ github.ref }}
75+
- name: Setup SSH agent to connect to deploy server
76+
run: |
77+
mkdir -p ~/.ssh
78+
echo "${EDUKAFORA_SSH_KEY}" > ~/.ssh/id_ed25519
79+
chmod 600 ~/.ssh/id_ed25519
80+
ssh-keyscan -t ed25519 ${EDUKAFORA_HOST} >> ~/.ssh/known_hosts
81+
env:
82+
EDUKAFORA_SSH_KEY: ${{ secrets.EDUKAFORA_SSH_KEY }}
83+
EDUKAFORA_HOST: ${{ vars.EDUKAFORA_HOST }}
84+
- name: Prepare new VSCode4Teaching version
85+
run: |
86+
scp docker-compose.yml ${EDUKAFORA_USER}@${EDUKAFORA_HOST}:${EDUKAFORA_PATH}/compose-new.yml
87+
ssh ${EDUKAFORA_USER}@${EDUKAFORA_HOST} "cd ${EDUKAFORA_PATH} && docker compose -f compose-new.yml pull --policy missing"
88+
env:
89+
EDUKAFORA_HOST: ${{ vars.EDUKAFORA_HOST }}
90+
EDUKAFORA_USER: ${{ vars.EDUKAFORA_USER }}
91+
EDUKAFORA_PATH: ${{ vars.EDUKAFORA_PATH }}
92+
- name: Stop VSCode4Teaching and change by new version
93+
run: |
94+
ssh ${EDUKAFORA_USER}@${EDUKAFORA_HOST} "cd ${EDUKAFORA_PATH} && docker compose down"
95+
ssh ${EDUKAFORA_USER}@${EDUKAFORA_HOST} "cd ${EDUKAFORA_PATH} && mv compose.yml compose-old.yml && mv compose-new.yml compose.yml"
96+
ssh ${EDUKAFORA_USER}@${EDUKAFORA_HOST} "cd ${EDUKAFORA_PATH} && docker compose up -d"
97+
env:
98+
EDUKAFORA_USER: ${{ vars.EDUKAFORA_USER }}
99+
EDUKAFORA_HOST: ${{ vars.EDUKAFORA_HOST }}
100+
EDUKAFORA_PATH: ${{ vars.EDUKAFORA_PATH }}
101+
- name: Clean up old version and SSH keys
102+
run: |
103+
ssh ${EDUKAFORA_USER}@${EDUKAFORA_HOST} "cd ${EDUKAFORA_PATH} && rm compose-old.yml"
104+
rm -r ~/.ssh
105+
env:
106+
EDUKAFORA_USER: ${{ vars.EDUKAFORA_USER }}
107+
EDUKAFORA_HOST: ${{ vars.EDUKAFORA_HOST }}
108+
EDUKAFORA_PATH: ${{ vars.EDUKAFORA_PATH }}

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
**/.DS_Store
2+
**/*.env*

.travis.yml

-47
This file was deleted.

Dockerfile

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
# Step 1: Compilation of Angular frontend
22
# It will be embedded as a static resource into Spring Boot backend
3-
FROM node:16.13.2 AS angular
3+
FROM node:18 AS angular
44
COPY vscode4teaching-webapp /usr/src/app
55
WORKDIR /usr/src/app
66
RUN ["npm", "install"]
77
RUN ["npm", "run", "build"]
88

99
# Step 2: Compilation of Maven project (generation of JAR)
10-
FROM maven:3.8.4-jdk-11 AS builder
10+
FROM maven:3.9.7-eclipse-temurin-11 AS builder
1111
COPY vscode4teaching-server /data
12-
COPY --from=angular /usr/src/app/dist /data/src/main/resources/static
12+
COPY --from=angular /usr/src/app/dist/vscode4teaching /data/src/main/resources/static/
1313
WORKDIR /data
1414
RUN ["mvn", "clean", "package"]
1515

1616
# Step 3: Generation of Docker image using the JAR previously built
17-
FROM adoptopenjdk/openjdk11:latest
18-
RUN apt-get update && apt-get install -y netcat && rm -rf /var/lib/apt/lists/*
19-
COPY --from=builder /data/target/vscode4teaching-server-*.jar ./app/vscode4teaching-server-*.jar
20-
COPY vscode4teaching-server/docker/waitDB.sh ./app/waitDB.sh
17+
FROM eclipse-temurin:11
18+
COPY --from=builder /data/target/vscode4teaching-server-*.jar ./app/vscode4teaching-server.jar
2119
EXPOSE 8080
22-
RUN ["chmod", "+x", "./app/waitDB.sh"]
23-
CMD ["./app/waitDB.sh"]
20+
ENTRYPOINT [ "java", "-jar", "./app/vscode4teaching-server.jar" ]

0 commit comments

Comments
 (0)