Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
pipeline {
agent any
stages {
stage("Initialization") {
steps {
script {
def version = sh(returnStdout: true, script: 'grep \'version=\' gradle.properties | cut -d\'=\' -f2')
buildName "${env.GIT_BRANCH.replace("origin/", "")}@${version}"
}
}
}
stage('Build') {
steps {
checkout scm
Expand Down
212 changes: 212 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# Springboard Plugin

A Gradle plugin for managing and configuring Edifice applications built on the ENT Core framework.

## Overview

The Springboard Plugin simplifies the development workflow for Edifice applications by providing automated tasks for:
- Configuration file generation
- Deployment extraction and organization
- Translation and help documentation management
- Theme extraction
- Integration testing with Gatling
- Module version management from GitHub

## Requirements

- Java 8
- Gradle 4.5
- Docker and Docker Compose (for build and deployment)

## Installation

### Using the Build Script

The plugin includes a build script that uses Docker Compose for consistent builds:

```bash
# Clean the project
./build.sh clean

# Install the plugin locally
./build.sh install

# Publish to repository (requires credentials)
./build.sh publish
```

### Manual Installation

```bash
gradle install
```

## Usage

### Applying the Plugin

In your project's `build.gradle`:

```groovy
plugins {
id 'fr.wseduc.springboard' version '3.2-zookeeper-SNAPSHOT'
}
```

### Available Tasks

#### `init`
Initialize a new Edifice project with all necessary files and directories:
- Creates directory structure (mods, deployments, i18n, etc.)
- Extracts deployments, helps, and translations
- Generates sample data and configuration files
- Sets up Docker Compose configuration
- Creates integration test scaffolding

```bash
gradle init
```

#### `generateConf`
Generate the `ent-core.json` configuration file from templates:

```bash
gradle generateConf
```

This task:
- Reads `conf.properties` and `gradle.properties`
- Merges with `default.properties`
- Automatically fetches missing base modules versions from GitHub
- Generates `ent-core.json` from `ent-core.json.template`

#### `extractDeployments`
Extract deployment artifacts from dependencies:

```bash
gradle extractDeployments
```

#### `extractHelps`
Extract help documentation from dependencies:

```bash
gradle extractHelps
```

#### `extractTranslations`
Extract i18n translation files:

```bash
gradle extractTranslations
```

#### `extractTheme`
Extract theme assets:

```bash
gradle extractTheme
```

#### `integrationTest`
Run Gatling integration tests:

```bash
gradle integrationTest
```

## Module Version Management

The plugin can automatically fetch the latest versions of Edifice modules from GitHub if they're not specified in your `gradle.properties`. Supported modules include:

- `mod-pdf-generator`
- `mod-mongo-persistor`
- `mod-image-resizer`
- `mod-zip`
- `mod-postgresql`
- `mod-json-schema-validator`
- `mod-sftp`
- `mod-webdav`
- `mod-sms-sender`

### Environment Variables

- `MODS_DEFAULT_BRANCH`: Set the default branch to fetch module versions from (defaults to trying `master`, then `main`)

## Project Structure

After running the `init` task, your project will have:

```
.
├── conf.properties # User configuration
├── default.properties # Default configuration values
├── ent-core.json.template # Configuration template
├── ent-core.json # Generated configuration
├── package.json # Node.js dependencies
├── docker-compose.yml # Docker setup
├── deployments/ # Extracted deployment artifacts
├── i18n/ # Translation files
├── static/help/ # Help documentation
├── mods/ # Application modules
├── sample-be1d/ # Sample data
├── neo4j-conf/ # Neo4j configuration
├── docker-entrypoint-initdb.d/ # Database initialization scripts
└── src/
└── test/
└── scala/
└── org/entcore/test/
├── scenarios/ # Gatling test scenarios
└── simulations/ # Gatling simulations
```

## Configuration Files

### conf.properties
User-specific configuration properties that override defaults.

### default.properties
Default configuration values merged during configuration generation.

### gradle.properties
Module versions and build configuration.

## Docker Support

The plugin includes Docker Compose configuration with platform-specific support:
- Automatically detects M1/ARM64 Macs
- Uses appropriate Docker images for the platform
- Configures PostgreSQL, MongoDB, and Neo4j services

## Development

### Building the Plugin

```bash
./build.sh install
```

### Publishing

```bash
# Set credentials in ~/.gradle/gradle.properties:
# odeUsername=<username>
# odePassword=<password>

./build.sh publish
```

## License

See LICENSE file for details.

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Submit a pull request

## Support

For issues and questions, please refer to the Edifice documentation or create an issue in the repository.
8 changes: 4 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ fi


clean () {
docker-compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle clean
docker compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle clean
}

install() {
# docker-compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle install publishToMavenLocal
docker-compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle install
# docker compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle install publishToMavenLocal
docker compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle install
}

publish() {
Expand All @@ -24,7 +24,7 @@ publish() {
echo "sonatypeUsername=$NEXUS_SONATYPE_USERNAME" >> "?/.gradle/gradle.properties"
echo "sonatypePassword=$NEXUS_SONATYPE_PASSWORD" >> "?/.gradle/gradle.properties"
fi
docker-compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle publish
docker compose run --rm -u "$USER_UID:$GROUP_GID" gradle gradle publish
}

for param in "$@"
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
group=fr.wseduc
archivesBaseName=springboard-plugin
version=4.0-SNAPSHOT
version=4.0-zookeeper-SNAPSHOT
69 changes: 68 additions & 1 deletion src/main/groovy/fr/wseduc/gradle/springboard/FileUtils.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,28 @@ import groovy.text.SimpleTemplateEngine
import org.gradle.api.Project

class FileUtils {

/**
* Map of module property names to module names on GitHub
* so we can fetch their version if not specified in gradle.properties.
*/
static final Map<String, String> MOD_NAME_MAPPINGS = [
modPdfgenerator: 'mod-pdf-generator',
modMongoPersistorVersion: 'mod-mongo-persistor',
modImageResizerVersion: 'mod-image-resizer',
modZipVersion: 'mod-zip',
modPostgresVersion: 'mod-postgresql',
modJsonschemavalidatorVersion: 'mod-json-schema-validator',
modSftpVersion: 'OPEN-ENT-NG/mod-sftp',
modWebdavVersion: 'OPEN-ENT-NG/mod-webdav',
modSmsproxyVersion: 'mod-sms-sender'
]

static def createFile(String propertiesFile,
String gradleFile,
String templateFileName,
String outputFileName) {
String outputFileName,
logger) {
def props = new Properties()
def file = new File(propertiesFile)
def rootDirectory = file.getParentFile()
Expand All @@ -32,6 +49,7 @@ class FileUtils {
bindings[prop] = defaultProps.getProperty(prop)
}
}
populateModuleVersionsNotInBindings(bindings, logger)
def engine = new SimpleTemplateEngine()
def templateFile = new File(templateFileName)
def output = engine.createTemplate(templateFile).make(bindings)
Expand All @@ -43,6 +61,55 @@ class FileUtils {
fileWriter.close()
}

/**
* For each module defined in MOD_NAME_MAPPINGS, if the corresponding
* property is not defined in the bindings map, fetch the latest release
* version from GitHub and add it to the bindings.
*/
static def populateModuleVersionsNotInBindings(Map bindings, logger) {
String modsDefaultBranch = System.getenv("MODS_DEFAULT_BRANCH")
MOD_NAME_MAPPINGS.each { key, modName ->
if (!bindings.containsKey(key)) {
logger.lifecycle("Fetching latest release version for module: " + modName)
// Fetch raw pom.xml from GitHub for the module. It will successively try
// the default branch (if defined in env MODS_DEFAULT_BRANCH), then master,
// then main.
// If it still does not exist raise an error
String[] branches = []
if (modsDefaultBranch != null && !modsDefaultBranch.isEmpty()) {
branches = [modsDefaultBranch, 'master', 'main']
} else {
branches = ['master', 'main']
}
String latestVersion = null
for (String branch : branches) {
try {
String modUrl;
if (modName.contains('/')) {
modUrl = modName
} else {
modUrl = "edificeio/" + modName
}
URL pomUrl = new URL("https://raw.githubusercontent.com/" + modUrl + "/refs/heads/" + branch + "/pom.xml")
InputStream pomStream = pomUrl.openStream()
String pomContent = pomStream.getText("UTF-8")
// Parse the xml and extract the version of the artifact
def pomXml = new XmlSlurper().parseText(pomContent)
latestVersion = pomXml.version.text()
break
} catch (Exception e) {
// Continue to next branch
}
}
if (latestVersion == null) {
throw new RuntimeException("Could not find the latest version of module: " + modName)
}
logger.lifecycle("Using latest version for module " + modName + " : " + latestVersion)
bindings[key] = latestVersion
}
}
}

/**
* Removes from the specified props the properties that are not
* useful for the generation of the entcore.json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ class SpringboardPlugin implements Plugin<Project> {
void apply(Project project) {
project.task("generateConf") << {
def rootDir = project.getRootDir().getAbsolutePath()
FileUtils.createFile("${rootDir}/conf.properties", "${rootDir}/gradle.properties", "${rootDir}/ent-core.json.template", "${rootDir}/ent-core.json")
FileUtils.createFile(
"${rootDir}/conf.properties",
"${rootDir}/gradle.properties",
"${rootDir}/ent-core.json.template",
"${rootDir}/ent-core.json",
project.logger)
}

project.task("extractDeployments") << {
Expand Down
7 changes: 5 additions & 2 deletions src/main/resources/conf.properties
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ passwordRegex=.*
skins={"localhost:8090":"raw"}
activationAutoLogin=false
signKey=
xitiSwitch=
directoryCalendarSwitch=
adminZimbra=
samlMetadataFolder=
Expand All @@ -76,4 +75,8 @@ cantooOptionalFeatureScriptPath=
restrictCRUDToADMC=
visiblesSearchType=
getVisibleStrategy=
debounceTimeToAutoSave=5000
debounceTimeToAutoSave=5000
xitiSwitch=
magnetoWebsocketMaxUsers=5000
magnetoWebsocketMaxUsersPerBoard=500
magnetoWebsocketPort=9092
Loading