Migration Guide
Introduction
This is a migration guide for projects that have been created in the past and do not use the project-expanders
yet. New projects should use the ns-initializer
script to be generated.
The migration is described in two steps which can be implemented as two separate pull requests:
- Modify the project setup to be what the
project-expanders
expect. A lot of files (the whole software project) will be moved. - Add the
project-expanders
to the project. Not everything is described in this guide. This is a major technical change on your projects. It does not keep into account any specifics of your project. Handle with care!
Definitions
- bold: directories
- software-project-name(kebab-case): kebab-cased version of the software project name
@angular
: label indicating that this is for projects using the angular frontend.
// replace the softwareProjectName
software-project-name(kebab-case)
Code block indication that the softwareProjectName
should be replaced with the software-project-name
.
In the code we mention artifact groups like nsapp
or nsapp/software-project-name(kebab-case)
. Just like the softwareProjectName
this is dependent on your project and is extracted from the Docker image name
Image names and versions are determined as follows: <service.artifact.group>/<service.artifact.technicalName>:<service.artifact.version or project.version or latest>
This means that if no version is specified the project version is used. This has one exception. If an image is used without a version in a isLocal (development) environment, then latest
is used.
This should become clear once the model has been defined.
Preparation
Before you start, make sure that any compose file used on Jenkins does NOT contain ANY volume mounts that are bind mounts. Mounting a directory that does not exist will cause Docker to create it - breaking Jenkins. If you absolutely need to add bind mounts to your Jenkins compose file, they must contain the create_host_path: false
and read_only: true
options.
- Make sure nss is up to date!
- If you don't have it installed yet: Installation
- Make sure you are on a clean branch from develop!!
- In the unlikely case you don’t use git. Take a backup.
Section 1: Moving files
The following files can be moved into the project/software-project-name(kebab-case) directory:
- angular/
@angular
- application/
- components/
- conf/
- docker/ -> docker/backend-image/
@angular
- docker/ -> docker/software-project-name(kebab-case)-image/
- scripts/
- settings/
- Jenkinsfile
- pom.xml
- README.md
- any other softwareProject specific directories or files Do not move the following files:
- CHANGELOG.md
- renovate.json
- .editorconfig
- .gitignore
Since the Jenkinsfile
has been moved into a subfolder within the project, Jenkins will not find it. Create another Jenkinsfile
on the root level of the project with the following content:
node {
checkout scm
// Replace the softwareProjectName
load 'project/software-project-name(kebab-case)/Jenkinsfile'
}
Your project should now look something like this:
project/
├── software-project-name(kebab-case)/
│ └── angular/
│ └── applications/
│ └── components/
│ └── conf/
│ └── docker/
│ └── software-project-name(kebab-case)-image/
│ └── sql/
│ └── BASE/
│ └── V1.0.0__initial_provision.sql `adapt to your base!`
│ └── MIGRATIONS/
│ └── 1.0.0/
│ └── V2024.01.01.0900__a_previous_database_migration.sql
│ └── PREV/ `to keep historic migration scripts, usually after re-basing`
│ └── .gitkeep
│ └── NEXT/
│ └── V2025.01.01.0900__a_database_migration.sql
│ └── .gitkeep
│ └── scripts/
│ └── settings/
│ └── Jenkinsfile
│ └── pom.xml
│ └── README.md
├── CHANGELOG.md
├── Jenkinsfile
├── README.md
├── renovate.json
├── .gitignore
.
Make sure the jenkinsfile is adjusted to compensate for the Docker folders moving!
If your project used the pom.info in the Jenkinsfile, to make sure your build is successful, make sure you have a pom.xml
on the level jenkins is reading the pom info from and that it matches the information of the software project.
It is a recommended to add a back
button in the README in the software project with [back](../../README.md)
The sql
folder structure is obligatory if you want to use the project.artifact.moveSqlScriptsOnRelease
option.
Make a pull request and make sure all builds are successful.
After this merge everyone will have to reimport the softwareProject in their μRadiant.
Section 2: Apply the project expanders
Step 1: Add the basic setup
Create the following directories and files in your project:
- .nsproject/
new
- model/
new
- projectSetup.xml
new
- projectSetup.xml
- expansionSettings.xml
new
- model/
- scripts/
- expand_project_setup.nss
new
- harvest_project_setup.nss
new
- expand_project_setup.nss
- project/
- docker/
- software-project-name/
- in this folder move the prepare.sh -> **scripts/**prepare.sh
moved
- in this folder move the prepare.sh -> **scripts/**prepare.sh
- software-project-name/
- .cleanExclude
new
- docker/
- .gitignore
new
- Jenkinsfile
updated
- pom.xml
new
- README.md
new
File contents
- projectSetup.xml
- expansionSettings.xml
- expand_project_setup.nss
- harvest_project_setup.nss
- Jenkinsfile
- .cleanExclude
- .gitignore
- pom.xml
- README.md
<project xmlns="https://schemas.normalizedsystems.org/xsd/project/2/1/0">
<name>projectSetup</name>
<!-- Replace the projectVersion -->
<version>projectVersion</version>
</project>
<expansionSettings>
<modelDirectory>..</modelDirectory>
<expansionDirectory>../project</expansionDirectory>
<expansions>
<expansion>
<type component="project" name="ProjectSetup"/>
<target>projectSetup</target>
</expansion>
</expansions>
<expansionResources>
<expansionResource name="net.democritus.project:jee-application-project-expanders" version="0.6.1"/>
<expansionResource name="net.democritus.project:jee-application-jenkins-ci-expanders" version="0.3.4"/>
</expansionResources>
</expansionSettings>
#!/usr/bin/env nss
import java.nio.file.Files
dir(ctx.script.path.parent) {
ns {
expand {
clean(false)
}
}
}
#!/usr/bin/env nss
import java.nio.file.Files
dir(ctx.script.path.parent) {
ns {
harvest {
clean(true)
}
}
}
node {
checkout scm
ansiColor('xterm') {
sh 'mvn clean expanders:expand'
}
// Replace the softwareProjectName
load 'project/software-project-name(kebab-case)/Jenkinsfile'
}
# Do not clean anything
*
# Project Setup
project/.gitignore
# Maven
*.versionsBackup
# Vscode
.vscode*
.devcontainer
# Intellij
.idea
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.normalizedsystems</groupId>
<!-- Replace the projectName -->
<artifactId>projectName-project</artifactId>
<!-- Replace the projectVersion -->
<version>projectVersion</version>
<properties>
<expanders-maven-plugin.version>2024.6.0</expanders-maven-plugin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>net.democritus.maven.plugins</groupId>
<artifactId>expanders-maven-plugin</artifactId>
<version>${expanders-maven-plugin.version}</version>
<configuration>
<expansionSettings>.nsproject/expansionSettings.xml</expansionSettings>
</configuration>
</plugin>
</plugins>
</build>
</project>
# Project
## Scripts
- `expand_project_setup.nss` Will expand the project setup
- `harvest_project_setup.nss` Will harvest the project setup
## SoftwareProjects
// Replace the softwareProjectName
- [softwareProjectName](project/software-project-name(kebab-case)/README.md)
Step 2: Removing files
The following files can be removed (if present):
- project/
- software-project-name(kebab-case)/
- conf/
- nsmr.xml
- docker/
- software-project-name-image/
- Dockerfile
- software-project-name-image/
- scripts/
- *.nss
- package.json
- conf/
- software-project-name(kebab-case)/
Any .nss
script that is not generated by the project setup should be self-contained. No more file imports.
Step 3: Creating the project setup model
Open the project setup in the μRadiant. Do this by importing the expansionSettings.xml
in the .nsproject
folder of your project. Create the following elements with the µRadiant
- Editing this is only available in μRadiant v2 (or higher) with the
org-normalizedsystems-northstar-project-plugin
(mrp-project-plugin
) installed - When importing the project from
expansionSettings.xml
in μRadiant v2 on linux, hidden files (ex:.nsproject/
) are not shown by default, make sure you tick the show hidden option. - μRadiant v2 currently doesn’t support the open folder functionality for the project setup (as this doesn’t use the
conf/
folder)
Model
Here we will highlight the different elements in the model to clarify their purpose. This is mainly related to Docker and Jenkins artifacts here but other systems like Tekton could be included in the future.
projectSetup::artifact
- These are the artifacts used or produced by the
projectSetup::softwareProject
.
- These are the artifacts used or produced by the
projectSetup::environment
- These describe useful environments for development, Jenkins pipelines or production deployments.
projectSetup::service
- These are the services that are used in the environments, they can be external or use artifacts created by the
projectSetup::softwareProject
.
- These are the services that are used in the environments, they can be external or use artifacts created by the
projectSetup::softwareProject
- This is the softwareProject creating the artifacts that are used to build the services
projectSetup::pipeline
- describes the build pipline for the project
projectSetup::stage
- describes the stages in the build pipeline for the project.
Artifacts
Neither the artifact name
nor the technicalName
should not contain any /
! If there is a group for the Docker images they should be added as the group field.
Below we will use the nsapp
group as an example.
Project with an Angular frontend
frontendImage
- technicalName:
frontend
- group:
nsapp/software-project-name(kebab-case)
- type:
angular-frontend-image
- technicalName:
backendImage
- technicalName:
backend
- group:
nsapp/software-project-name(kebab-case)
- type:
jee-application-image
- technicalName:
gatewayImage
- technicalName:
gateway
- group:
nsapp/software-project-name(kebab-case)
- type:
gateway-image
- technicalName:
databaseImage
- technicalName:
postgres
- version:
17.2
(use your current postgres version) - type:
custom
- technicalName:
Project without an Angular frontend
software-project-name-image
- technicalName:
software-project-name(kebab-case)
- group:
nsapp
- type:
jee-application-image
- technicalName:
databaseImage
- technicalName:
postgres
- version:
17.2
(use your current postgres version) - type:
custom
- technicalName:
Environments
default
- options:
project.environment.isLocal
- options:
SoftwareProjects
Project with an Angular frontend
softwareProjectName
- type: jee-application
- artifacts:
projectSetup::frontend-image
projectSetup::backend-image
projectSetup::gateway-image
- pipelines
build-pipeline
- stages
validate
- type:
validate
- type:
expand
- type:
expand
- type:
build
- type:
build
- type:
deploy
- type:
deploy
- type:
report
- type:
report
- type:
analyze
- type:
analyze
- type:
- (possible) options:
- project.pipeline.slackChannel:
team-jenkins-slack-channel
- project.pipeline.changelogSlackChannel:
team-release-slack-channel
- project.pipeline.onlyReportChanges
- project.pipeline.noReleasePromotion
- project.pipeline.relaxBranchVersionCheck
- project.pipeline.slackChannel:
- stages
- options:
- project.softwareProject.frontend:
angular-app-name
@angular
- project.softwareProject.frontend:
Project without an Angular frontend
softwareProjectName
- type: jee-application
- artifacts:
softwareProjectNameImage
- pipelines
build-pipeline
- stages
validate
- type:
validate
- type:
expand
- type:
expand
- type:
build
- type:
build
- type:
deploy
- type:
deploy
- type:
report
- type:
report
- type:
analyze
- type:
analyze
- type:
- (possible) options:
- project.pipeline.slackChannel:
team-jenkins-slack-channel
- project.pipeline.changelogSlackChannel:
team-release-slack-channel
- project.pipeline.onlyReportChanges
- project.pipeline.noReleasePromotion
- project.pipeline.relaxBranchVersionCheck
- project.pipeline.slackChannel:
- stages
- options:
- project.softwareProject.frontend:
angular-app-name
@angular
- project.softwareProject.frontend:
Services
Project with an Angular frontend
frontend
- artifact:
projectSetup::frontendImage
- environments
projectSetup::default
- type:
angular-frontend
- softwareProject:
projectSetup::softwareProject
- artifact:
backend
- artifact:
project::backendImage
- environments
projectSetup::default
- type:
jee-application
- softwareProject:
projectSetup::softwareProject
- artifact:
gateway
- artifact:
projectSetup::gatewayImage
- environments
projectSetup::default
- type:
gateway
- softwareProject:
projectSetup::softwareProject
- artifact:
database
- artifact:
projectSetup::databaseImage
- environments
projectSetup::default
- type:
database
- artifact:
Project without an Angular frontend
software-project-name
- artifact:
projectSetup::softwareProjectName
- environments
projectSetup::default
- type:
jee-application
- softwareProject:
projectSetup::softwareProject
- artifact:
database
- artifact:
projectSetup::databaseImage
- environments
projectSetup::default
- type:
database
- artifact:
Step 4: Run!
You should now be ready to use the project-expanders
!
To do so, do the following in the μRadiant
- In the project setup, go to
build
=>script
and run thescripts/expand_project_setup.nss
script
- This should provide you with all the files necessary to build and deploy the project.
Here you transfer all the necessary data from your compose files into the environment/override compose files
- Ports
- Environment variables
- Now build your application using μRadiant or the nsScripts that have been expanded to your project setup.
- And finally, run
start_default_services.nss
. The local docker containers should be started and you should have an environment deployed on our machine! - To undeploy, run
stop_default_services.nss
Any files can still be created next to the expanded files.
Step 5: Opportunities for improvement
Please do provide us with any and all feedback you have! As this is a substantial change, there are a lot of details not mentioned in this guide.