fixed jenkins file and updated readme
Locusworks Team/portal-webapp/pipeline/head This commit looks good

This commit is contained in:
iparenteau committed 2026-09-04 15:39:29 -05:00
1 parent a6df549919
commit f0716b0073
3 files changed
+159 -183

No files matched your search

Vendored
+5 -6
View File
@@ -41,12 +41,11 @@ pipeline {
stage('Prepare OWASP cache') { stage('Prepare OWASP cache') {
steps { steps {
withCredentials([string(credentialsId: 'nvd-api-key', variable: 'NVD_API_KEY')]) { lock(resource: 'owasp-nvd-cache') {
lock(resource: 'owasp-nvd-cache') { withMaven(maven: 'maven-3.9.16', globalMavenSettingsConfig: 'locusworks-settings') {
withMaven(maven: 'maven-3.9.16', globalMavenSettingsConfig: 'locusworks-settings') { // Dependency-Check uses nvdApiKey from pom.xml.
sh 'mkdir -p "$HOME/.cache/dependency-check"' sh 'mkdir -p "$HOME/.cache/dependency-check"'
sh 'mvn -B org.owasp:dependency-check-maven:13.0.0:update-only -DdataDirectory="$HOME/.cache/dependency-check"' sh 'mvn -B org.owasp:dependency-check-maven:13.0.0:update-only -DdataDirectory="$HOME/.cache/dependency-check"'
}
} }
} }
} }
+154 -157
View File
@@ -1,173 +1,170 @@
# SETUP - Development # Portal
---
1. Clone the repository from BigMac:
- Add your public key to BigMac account.
- Clone the repository: `git clone "ssh://git@bigmac.locusworks.net:8010/saipt/portal-webapp.git"`
2. Create/Edit `settings.xml` in your `.m2` folder (see next section for example)
3. Change directories into the project and run `mvn clean install` (this may take a while).
4. Start the executable Spring Boot application with `java -jar portal_webapp/target/portal_webapp-1.0.0-RELEASE.jar`.
5. Browse to `http://localhost:8080/portal/`.
Application configuration is stored under `${user.home}/.portal` by default. Override this persistent location with the `PORTAL_HOME` environment variable or the `-Dportal.home=/path/to/portal` JVM property. The directory contains `portal.properties`, the AES seed, logger settings, logs, and temporary key files. Portal manages scripts, repositories, credentials, files, and scheduled jobs. Its Angular client is bundled into an executable Spring Boot JAR with embedded Tomcat.
Local runs use a persistent H2 database by default. Set `dbType=mysql` in `portal.properties` only when an external MySQL server is intended; H2 and MySQL have separate connection and credential properties. ## Requirements
External MySQL deployments require MySQL Server 8.4 or newer with Connector/J 26.7.0. | Component | Configuration |
| --- | --- |
| Java | JDK 21; check the active runtime with `mvn -v` |
| Maven | Maven 3.9.x; Jenkins uses `maven-3.9.16` |
| Backend | Spring Boot 4.1.1, embedded Tomcat 11.0.25 |
| Frontend | Angular 22; Node.js 24.20.0 and npm 12.0.2 provisioned by Maven |
| Default database | Persistent H2 in MySQL compatibility mode |
| External database | MySQL Server 8.4+ with Connector/J 26.7.0 |
## npm Versions are defined in [pom.xml](pom.xml) and [portal_client/package.json](portal_client/package.json). The frontend lockfile pins the installed npm dependency tree. Building requires access to the Locusworks Nexus repository, npm registry, and dependency-check data services. A global Node.js or npm installation is not required for Maven builds.
---
npm is used to install the Angular client dependencies declared in `portal_client/package.json`.
The Maven build provisions the supported Node.js LTS and npm versions declared in the root `pom.xml`; a global installation is not required for Maven builds. ## Build and run
From `portal_client`, run `npm ci` for a reproducible install, `npm test` for unit tests, and `npm run build` for the production bundle. Angular CLI discovers application imports and static assets directly; no legacy asset-injection manifest is required. Add your SSH public key to your Gitea account, then clone and build:
The `allowScripts` entries in `package.json` approve specific versions of the native Angular build helpers. Review and renew those entries when upgrading the corresponding packages. SockJS remains an explicitly allowed CommonJS dependency for the server's SockJS transport. STOMP uses its ESM entry through the TypeScript path mapping because version 7.3.0's browser export selects UMD. ```sh
git clone ssh://gitea@gitea.locusworks.net:7999/locusworks/portal-webapp.git
cd portal-webapp
mvn clean install
java -jar portal_webapp/target/portal_webapp-1.0.0-RELEASE.jar
```
## Dependency checks Open **http://localhost:8080/portal/**. The entry page redirects to `/portal/client/`, which uses hash-based routing. Use the corresponding JAR filename if the project version has changed.
`mvn clean install` runs OWASP Dependency-Check. NVD, RetireJS, and the npm lockfile audit remain enabled; the npm audit includes development dependencies. The Node Package Analyzer skips development dependencies to avoid treating uninstalled native binaries for other platforms as missing application packages. The build installs frontend dependencies with `npm ci`, builds and tests the client, compiles and tests the Java modules, runs dependency checks, packages the executable JAR, and installs Maven artifacts into the local repository. It does not publish to Nexus or start the application.
Sonatype OSS Index requires credentials and is opt-in. Configure a Maven `settings.xml` server with ID `oss-index`, your account username, and API token, then run `mvn clean install -Dportal.ossIndexEnabled=true` to include it. ### Maven settings
## H2 tests The POM defines the `locusworks-public` dependency/plugin repository and the `nexus-release` and `nexus-snapshot` deployment repositories. If authentication is required, configure matching server IDs in your user Maven settings (`~/.m2/settings.xml`, or `%USERPROFILE%\.m2\settings.xml` on Windows):
---
Tests use an isolated in-memory H2 database through the `portal.database.*` system-property overrides. Production continues to default to MySQL.
Run the common-module datasource test with: ```xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0">
`mvn -pl portal_common -am test` <servers>
<server>
<id>locusworks-public</id>
## Settings.xml <username>${env.NEXUS_USERNAME}</username>
--- <password>${env.NEXUS_PASSWORD}</password>
If developing on the NGGN the proxy settings are needed to download the libraries </server>
Sample:
```xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<proxies>
<proxy>
<id>locusworks-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>eastproxy.locusworks.net</host>
<port>80</port>
<username>(your MyID)</username>
<password>(your login password)</password>
</proxy>
<proxy>
<id>locusworks-proxy2</id>
<active>true</active>
<protocol>https</protocol>
<host>eastproxy.locusworks.net</host>
<port>80</port>
<username>(your MyID)</username>
<password>(your login password)</password>
</proxy>
</proxies>
<servers>
<server>
<id>flyway-localhost</id>
<username>root</username>
<password>(mysql root password)</password>
</server>
</servers> </servers>
</settings> </settings>
``` ```
## Running Spring Boot Supply those environment variables before building. Add `nexus-release` and `nexus-snapshot` server entries when publishing. The Nexus base URL defaults to `https://nexus.locusworks.net` and can be overridden with `-Dnexus.repo=https://your-nexus-host`.
---
The application is packaged as an executable JAR and does not require a separately installed application server. Spring Boot supplies the embedded web server. For production, NGINX or Apache can proxy ports 80 and 443 to the application on port 8080. ## Application configuration
#### NGINX Portal resolves its writable home directory in this order:
1. In the default /etc/nginx/conf.d add a file called portal.conf
1. JVM property `-Dportal.home=/path/to/portal`.
2. Populated it with the values below 2. Environment variable `PORTAL_HOME`.
``` conf 3. `${user.home}/.portal`.
proxy_cache_path /tmp/NGINX_cache/ keys_zone=backcache:10m;
```sh
map $http_upgrade $connection_upgrade { java -Dportal.home=/var/lib/portal -jar portal_webapp/target/portal_webapp-1.0.0-RELEASE.jar
default upgrade; ```
'' close;
} On Windows, use an absolute path such as `-Dportal.home=D:/Portal/data`. Put JVM properties before `-jar`.
upstream portal_app { The home directory holds `portal.properties`, the AES seed, `portal-loggers.properties`, logs, temporary key files, and the default H2 database under `data/`. Keep it separate from build output and preserve it when replacing the JAR. Encrypted settings depend on the AES seed, so back them up together.
# Use IP Hash for session persistence
ip_hash; | File | Purpose |
| --- | --- |
# List of Portal application instances | [application.properties](portal_webapp/src/main/resources/application.properties) | Spring Boot context path, session, multipart, and JPA settings |
server 127.0.0.1:8080; | [portal.properties](portal_webapp/src/main/resources/portal.properties) | Defaults used to initialize and reconcile the persistent Portal configuration |
}
For another HTTP port, append `--server.port=8081` to the Java command. The frontend assumes the `/portal` context path; changing it also requires updating client paths and rebuilding.
server {
listen 80; ### Databases
server_name portal.viprcenter.com;
client_max_body_size 0; New installations default to `dbType=h2`. H2 uses a persistent file database and needs no separate database server. Existing installations retain their configured `dbType`; there is no automatic production switch to MySQL.
# Redirect all HTTP requests to HTTPS For external MySQL, set `dbType=mysql` and configure `dbHost`, `dbPort`, `dbUsername`, `dbPassword`, `dbRootUser`, and `dbRootPassword` in the persistent Portal settings. Runtime migrations use the root connection; normal application access uses the application connection. H2 has separate `h2Url`, `h2Username`, and `h2Password` settings.
location / {
return 301 https://$server_name$request_uri; Nonblank database passwords in `portal.properties` are read as encrypted values. Use Portal's configuration facilities to save encrypted credentials instead of putting plaintext in those fields. Connector/J 26.7.0 requires MySQL Server 8.4 or newer; see the [MySQL release notes](https://dev.mysql.com/doc/relnotes/connector-j/en/news-26-7-0.html).
}
} ## Frontend development
server { Build the complete project once to provision the pinned tools. From `portal_client`, use the local executables to avoid picking up a different global npm version.
listen 443 ssl http2;
server_name portal.viprcenter.com; PowerShell:
client_max_body_size 0;
```powershell
ssl_certificate /etc/nginx/ssl/portal.viprcenter.com.crt; .\node\node.exe .\node\node_modules\npm\bin\npm-cli.js ci
ssl_certificate_key /etc/nginx/ssl/portal.viprcenter.com.key; .\node\node.exe .\node\node_modules\npm\bin\npm-cli.js run build
.\node\node.exe .\node\node_modules\npm\bin\npm-cli.js test
ssl_session_cache shared:SSL:1m; ```
ssl_prefer_server_ciphers on;
Linux/macOS:
# WebSocket configuration
location / { ```sh
proxy_pass http://portal_app; ./node/node ./node/node_modules/npm/bin/npm-cli.js ci
proxy_http_version 1.1; ./node/node ./node/node_modules/npm/bin/npm-cli.js run build
proxy_set_header Upgrade $http_upgrade; ./node/node ./node/node_modules/npm/bin/npm-cli.js test
proxy_set_header Connection $connection_upgrade; ```
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr; With matching Node.js and npm versions on `PATH`, the equivalent commands are `npm ci`, `npm run build`, and `npm test`. The `start` script runs the Angular development server, but this project has no backend proxy configuration; API calls and realtime connections expect the `/portal` backend on the same origin. Use the packaged application for an integrated local run.
proxy_set_header X-Forwarded-Host $remote_addr;
} Client output goes to `portal_client/dist/` and is copied into the backend JAR at build time. Rebuild the backend to include changed client assets. Login, dashboard, and feature pages load on demand; the initial-bundle warning budget remains 500 kB.
}
``` The `allowScripts` entries in `package.json` approve specific versions of native build helpers. Review and renew them when upgrading those dependencies. SockJS is explicitly allowed as a CommonJS dependency for the existing transport. STOMP uses its shipped ESM entry through the TypeScript path mapping because its 7.3.0 browser export selects UMD. npm warnings and failures remain visible; routine npm notices are omitted.
3. Save the file ## Tests and dependency checks
4. Modify `/etc/nginx/nginx.conf` Run the complete verification with `mvn clean install`. To run the datasource test and its prerequisite Java modules:
5. In the http section of the conf file add `include /etc/nginx/conf.d/portal.conf` ```sh
mvn -pl portal_common -am test
6. Restart NGINX ```
7. Navigate to the url. It should redirect to 443 The datasource test uses isolated in-memory H2 through `portal.database.*` JVM overrides and clears them afterward. It does not test an external MySQL instance. Frontend tests use Vitest through Angular CLI, including lazy login rendering and authentication redirects. Java test results are written to each module's `target/surefire-reports/` directory.
OWASP Dependency-Check runs during `verify`, which is included in `install`. HTML reports are written to `target/dependency-check-report.html` in the root and module directories. NVD, RetireJS, and npm lockfile auditing remain enabled. The npm audit includes development dependencies; the Node Package Analyzer skips them to avoid warnings about uninstalled native binaries for other platforms. The POM sets `failOnError=false` for Dependency-Check, so review its output and reports even when Maven succeeds.
#### Apache
Sonatype OSS Index requires credentials and is opt-in. Add a server named `oss-index` to Maven settings with your account username and API token as the password, then run:
1. In apaches `httpd.conf` file add the following
``` conf ```sh
Listen 80 mvn clean install -Dportal.ossIndexEnabled=true
Listen 443 ```
<VirtualHost *:80> ## Deployment
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(.*)$ Deploy `portal_webapp/target/portal_webapp-<version>.jar` and run it with Java 21 under your service manager. A separately installed Tomcat is not required. Configure a persistent Portal home writable by the service account.
RewriteRule ^(.*)$ https://%1$1 [R=Permanent,L,QSA]
</VirtualHost> [scripts/deploy-server.sh](scripts/deploy-server.sh) copies the built JAR to `deploy/portal.jar` by default. `PORTAL_DEPLOY_DIR` changes the destination; `PORTAL_SERVICE` requests a systemd service restart after copying. In this helper, `PORTAL_HOME` refers to the **source checkout**, unlike the application's runtime data directory. Use `-Dportal.home` in the Java service command to keep those locations distinct.
<VirtualHost *:443> ### Reverse proxy
SSLEngine On
SSLCertificateFile /etc/apache/ssl/portal.viprcenter.com.crt Terminate HTTPS at NGINX or Apache and preserve `/portal/` when forwarding to the backend on port 8080. Realtime endpoints need WebSocket upgrades as well as ordinary HTTP forwarding.
SSLCertificateKeyFile /etc/apache/ssl/portal.viprcenter.com.key
For NGINX, place the `map` in the `http` context and the `location` inside your site's HTTPS `server` block:
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/ ```nginx
ProxyPassReverse / http://127.0.0.1:8080/ map $http_upgrade $connection_upgrade {
</VirtualHost> default upgrade;
``` '' close;
2. Restart and try navigating }
# Inside the HTTPS server block:
location /portal/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600s;
}
```
Supply your hostname, TLS certificates, and HTTP-to-HTTPS redirect in the surrounding configuration. Match proxy upload limits to the application's limits (10 MB by default). See [NGINX WebSocket proxying](https://nginx.org/en/docs/http/websocket.html). For Apache, enable `mod_proxy` and `mod_proxy_http` and configure WebSocket forwarding for your installed version; see the [Apache proxy documentation](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html).
## Jenkins
[Jenkinsfile](Jenkinsfile) defines a multibranch pipeline that checks out source, assigns a build version, updates a shared OWASP cache, runs `mvn clean verify`, publishes Java test results, archives JARs, and conditionally publishes Maven artifacts to Nexus.
| Branch | Version | Publish to Nexus |
| --- | --- | --- |
| `release/<version>` | `<version>.<build-number>-RELEASE` | Yes |
| `develop` | `develop.<build-number>-SNAPSHOT` | Yes |
| Other branches | `0.0.<build-number>-<sanitized-branch>-SNAPSHOT` | No |
The Jenkins agent needs a shell environment, JDK 21, Maven installation `maven-3.9.16`, and managed settings configuration `locusworks-settings`. Dependency-Check uses the existing `nvdApiKey` configuration in `pom.xml`; no separate Jenkins NVD credential is required. The pipeline uses the `owasp-nvd-cache` lock. Its deploy stage publishes artifacts; it does not restart an application server.
-20
View File
@@ -1,25 +1,5 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd"> xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<proxies>
<proxy>
<id>locusworks-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>eastproxy.locusworks.net</host>
<port>80</port>
<username>(your MyID)</username>
<password>(your login password)</password>
</proxy>
<proxy>
<id>locusworks-proxy2</id>
<active>true</active>
<protocol>https</protocol>
<host>eastproxy.locusworks.net</host>
<port>80</port>
<username>(your MyID)</username>
<password>(your login password)</password>
</proxy>
</proxies>
<servers> <servers>
<server> <server>
<id>flyway-localhost</id> <id>flyway-localhost</id>