[CI/CD] Add CI/CD workflow for extensions#50
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the extensions build and CI/CD pipeline to (a) run tests/coverage reporting in CI and (b) produce a Docker build context that includes built extension JARs, intended to enable publishing an “all extensions” manager image.
Changes:
- Add a
deploymentproject (Dockerfile + build context) and per-extension Gradle tasks to copy extension JARs intodeployment/build/extensions. - Update CI workflow to spin up the dev-testing docker-compose stack, run
./gradlew build, and build multi-arch Docker images. - Enable JaCoCo reporting across Java subprojects and adjust ENTSO-E test ignores.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
gradle.properties |
Disables parallel Gradle and adds camelVersion property. |
build.gradle |
Enables JaCoCo + report generation for Java subprojects. |
entsoe/src/test/.../EntsoeProtocolTest.groovy |
Removes CI-wide ignore and ignores a specific test. |
entsoe/build.gradle |
Adds copyExtension task to stage the built JAR into deployment/build/extensions. |
ems/build.gradle |
Adds copyExtension task to stage the built JAR into deployment/build/extensions. |
deployment/Dockerfile |
Defines an image that layers staged extensions onto openremote/manager:latest-core. |
deployment/build.gradle |
Copies Dockerfile into the Docker build context (but currently at configuration time). |
.github/workflows/release.yml |
Removes the old release workflow. |
.github/workflows/ci_cd.yml |
Overhauls CI to run docker-compose-based integration tests and build/publish Docker/Maven artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@codex review |
| FROM openremote/manager:latest-core | ||
|
|
||
| RUN mkdir -p /deployment/manager/extensions | ||
| COPY extensions /deployment/manager/extensions No newline at end of file |
| tasks.register("prepareDockerContext", Copy) { | ||
| from(layout.projectDirectory.file("Dockerfile")) | ||
| into(layout.buildDirectory) | ||
| } |
| username: ${{ secrets._TEMP_DOCKERHUB_USER }} | ||
| password: ${{ secrets._TEMP_DOCKERHUB_PASSWORD }} |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a504a2972
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| run: | | ||
| # Run build | ||
| # Make temp dir with 777 mask as docker seems to run as root | ||
| mkdir -pm 777 tmp |
There was a problem hiding this comment.
Create tmp under the OpenRemote checkout
This prepares tmp in the extensions checkout, but the compose file used two lines later is openremote/profile/dev-testing.yml, whose ../tmp:/storage bind resolves relative to the first -f compose file's directory (Docker documents paths as relative to the first compose file), i.e. openremote/tmp. In CI this chmods an unused directory while Compose creates/mounts openremote/tmp with default permissions, so tests that rely on the dev-testing shared storage can still hit the root-owned-directory problem this step is trying to avoid.
Useful? React with 👍 / 👎.
|
|
||
| # Release | ||
| release: | ||
| types: [ published ] |
There was a problem hiding this comment.
Exclude prereleases before pushing latest
Using the published release activity also runs for GitHub prereleases, but the release-only steps below push openremote/manager:latest and publish to Sonatype without checking github.event.release.prerelease. If someone publishes an RC/beta as a prerelease, this workflow will overwrite the production latest Docker tag and attempt a Maven release for that prerelease; add a prerelease guard or use a release activity that excludes prereleases.
Useful? React with 👍 / 👎.
| @@ -0,0 +1,4 @@ | |||
| FROM openremote/manager:latest-core | |||
There was a problem hiding this comment.
Pin the release image to the matching core
The release workflow tags the resulting image as the release version, but this Dockerfile always starts from the floating openremote/manager:latest-core. When an older release is rebuilt or when the core latest-core tag has advanced before the extension release runs, the image tagged with github.event.release.tag_name will contain a different manager core than the Gradle artifacts were built against, making the release image non-reproducible and potentially incompatible.
Useful? React with 👍 / 👎.
| -PkeystoreKeyAlias=$KEYSTORE_KEY_ALIAS -PkeystoreKeyPassword=$KEYSTORE_KEY_PASSWORD -PkeystoreFile=$PWD/keystore -PkeystorePassword=$KEYSTORE_PASSWORD | ||
| uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 | ||
| with: | ||
| platforms: linux/amd64,linux/arm64 |
There was a problem hiding this comment.
The docker/setup-qemu-action input is passed directly to tonistiigi/binfmt --install, and the action documents this field as architecture names such as arm64,riscv64,arm, not buildx platform strings. With linux/amd64,linux/arm64 here, the QEMU setup step can fail before both develop and release image builds; use arm64 or omit the input to install all emulators.
Useful? React with 👍 / 👎.
|
|
||
| # Release | ||
| release: | ||
| types: [ published ] |
There was a problem hiding this comment.
Avoid cancelling release runs with tag builds
Adding the release trigger while keeping the existing tag push trigger puts both runs in the same concurrency group because GitHub sets release GITHUB_REF to the tag ref. When a release is published while creating the tag, the tag-push build and the release-publish run can cancel each other under cancel-in-progress: true; if the push run wins, it only builds/tests and skips the Docker/Maven release steps.
Useful? React with 👍 / 👎.
|
@codex review |
| - name: Update openremoteVersion in gradle.properties | ||
| if: ${{ github.event_name != 'pull_request' }} | ||
| run: sed -i "s/^openremoteVersion = .*/openremoteVersion = $VERSION/" gradle.properties | ||
| env: | ||
| VERSION: ${{ inputs.version }} | ||
|
|
| - name: Build develop image | ||
| if: ${{ steps.is_main_repo.outputs.value && github.event_name != 'pull_request' }} | ||
| uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 |
| # Start the dev-testing stack | ||
| docker compose -f openremote/profile/dev-testing.yml up -d --no-build | ||
|
|
||
| ./gradlew build |
| tasks.register("copyExtension", Copy) { | ||
| dependsOn jar | ||
| from(jar.archiveFile) | ||
| into project(":deployment").layout.buildDirectory.dir("extensions") | ||
| } |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b324f77947
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if: ${{ github.event_name != 'pull_request' }} | ||
| run: sed -i "s/^openremoteVersion = .*/openremoteVersion = $VERSION/" gradle.properties | ||
| env: | ||
| VERSION: ${{ inputs.version }} |
There was a problem hiding this comment.
Gate version rewrite to manual dispatches
For push runs on main or a release tag, there is no workflow_dispatch inputs.version, but this step still runs for every non-PR event and rewrites gradle.properties to openremoteVersion = before ./gradlew build. The extension dependencies use openremoteVersion, so normal push/tag CI will build and publish with an empty OpenRemote dependency version instead of the committed 1.26.0; restrict this rewrite to dispatch runs or provide a push/tag default.
Useful? React with 👍 / 👎.
| - name: Build develop image | ||
| if: ${{ steps.is_main_repo.outputs.value && github.event_name != 'pull_request' }} | ||
| uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 |
There was a problem hiding this comment.
Limit develop pushes to main-branch builds
Because this condition is true for every non-PR event in this workflow, manual dispatches and release-tag pushes also push openremote/manager:develop. In those scenarios the selected/tagged ref can overwrite the develop image with release or manually selected contents; gate this step to the push event on refs/heads/main so only main updates the develop tag.
Useful? React with 👍 / 👎.
| run: | | ||
| # Run build | ||
| # Make temp dir with 777 mask as docker seems to run as root | ||
| mkdir -pm 777 tmp |
There was a problem hiding this comment.
Create the temp directory beside the compose profile
The checked-out openremote/profile/dev-testing.yml profile mounts ../tmp:/storage, and Compose resolves that relative to the openremote/profile compose file, so this creates /workspace/extensions/tmp while PostgreSQL actually mounts openremote/tmp. Docker will then create the mounted directory without the intended 0777 permissions, which can make the re-enabled integration tests fail when PostgreSQL tries to write to /storage; create openremote/tmp or run Compose from the OpenRemote checkout.
Useful? React with 👍 / 👎.
| @@ -0,0 +1,4 @@ | |||
| FROM openremote/manager:latest-core | |||
There was a problem hiding this comment.
Pin release images to the requested core tag
The release workflow tags the resulting image as ${{ inputs.version }}, but the Dockerfile always builds on the floating openremote/manager:latest-core base. When latest-core has moved past the version being released, the published openremote/manager:<version> image will contain a different Manager core than the extension dependencies selected with openremoteVersion; parameterize the base tag so release images use the matching <version>-core base.
Useful? React with 👍 / 👎.
This PR includes the following changes:
developimage on push to main and publish it to DockerHub with tagopenremote/manager:developincluding ALL extensions (except EMS).managerimage when a new release is created an publish it to DockerHub with tag'openremote/manager:latestandopenremote/manager:$versionincluding ALL extensions (except EMS).deploymentfolder so they can be included when building a new image.