-
Notifications
You must be signed in to change notification settings - Fork 14
ONC-XXXX - Create Docker image on branch push #2014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
edeb9fe
build: add secret-free Docker image for chpl-api
tmy1313 7dbfa2a
ci: publish chpl-api Docker image to GHCR
tmy1313 1cf2ee3
test: temporarily trigger docker-publish on pull_request
tmy1313 eafd1a8
ci: tag chpl-api image with build number, sha, and branch pointer
tmy1313 f11e1e5
docs: document required env vars for the chpl-api Docker image
tmy1313 5816d90
ci: disable provenance/sbom attestations for chpl-api image push
tmy1313 42578db
Revert "test: temporarily trigger docker-publish on pull_request"
tmy1313 419ec7d
ci: build chpl-api image on merge to environment branches
tmy1313 f9fad67
chore(docker): remove unused JWK_KEY signing-key mechanism
tmy1313 636e109
ci: add .dockerignore to shrink chpl-api image build context
tmy1313 7d1ede2
chore: remove orphaned .gitattributes rule for deleted entrypoint.sh
tmy1313 59e779b
ci: cancel in-flight docker-publish runs for the same branch
tmy1313 ea9b5d4
ci: run unit tests before building docker image
tmy1313 26a13a1
ci: fail fast on compile errors before building docker image
tmy1313 cfb9ae6
test: temporarily break a unit test to verify CI gate
tmy1313 70ab194
Revert "test: temporarily break a unit test to verify CI gate"
tmy1313 1d610f9
test: temporarily break compilation to verify CI gate
tmy1313 6892a31
Revert "test: temporarily break compilation to verify CI gate"
tmy1313 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .git | ||
| **/target/ | ||
| node_modules | ||
| .vscode | ||
| .claude |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| name: Publish Docker Image | ||
|
|
||
| on: | ||
| workflow_dispatch: {} | ||
| # One workflow, shared by every environment branch: a merge into any of | ||
| # these triggers a build tagged latest-<that-branch>. No per-branch copies | ||
| # or separate workflow files to keep in sync. | ||
| push: | ||
| branches: | ||
| - development | ||
| - qa | ||
| - staging | ||
| - production | ||
|
|
||
| # Publishes a floating latest-<branch> tag - without this, two runs for the | ||
| # same branch could race and let an older commit's build finish last, | ||
| # overwriting latest-<branch> with a stale image. | ||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: read | ||
| packages: write | ||
|
|
||
| jobs: | ||
| # Mirrors the "Run API Unit Tests" job in the Bamboo CHPL Development | ||
| # Deployment plan (chpl-build/chpl-build-dev): `mvn clean test` against | ||
| # chpl/pom.xml on JDK 21. Gates the image build so a broken build never | ||
| # gets published. | ||
| unit-tests: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up JDK 21 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| java-version: '21' | ||
| distribution: 'temurin' | ||
|
|
||
| - name: Run unit tests | ||
| env: | ||
| MAVEN_OPTS: -Xms512m -Xmx1024m | ||
| run: mvn -B clean test --file chpl/pom.xml | ||
|
|
||
| # Mirrors the "Build API" job (CompileApiTask) in the same Bamboo plan, and | ||
| # runs the exact `mvn clean package -DskipTests` command that docker/Dockerfile's | ||
| # build stage runs - so a compile/packaging failure shows up here, fast, | ||
| # instead of partway through the (slower) Docker build. | ||
| compile: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up JDK 21 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| java-version: '21' | ||
| distribution: 'temurin' | ||
|
|
||
| - name: Compile and package | ||
| env: | ||
| MAVEN_OPTS: -Xms512m -Xmx1024m | ||
| run: mvn -B clean package -DskipTests --file chpl/pom.xml | ||
|
|
||
| build-and-push: | ||
| needs: [unit-tests, compile] | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
|
|
||
| - name: Log in to GHCR | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Compute image metadata | ||
| id: meta | ||
| run: | | ||
| echo "image=ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT" | ||
| echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" | ||
| echo "branch=$(echo '${{ github.ref_name }}' | tr '/' '-')" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # This image contains no secrets - see docker/Dockerfile. Every environment | ||
| # (development/qa/staging/production) runs the exact same image; secrets are | ||
| # supplied as container environment variables at `docker run` time, not baked | ||
| # in here. | ||
| # | ||
| # Tags: | ||
| # build-<run_number> - immutable, sequential build number (github.run_number | ||
| # never repeats or goes backwards for this workflow) | ||
| # sha-<short-sha> - immutable, traces back to the exact commit | ||
| # latest-<branch> - floating pointer to the most recent build from that | ||
| # branch (latest-development, latest-qa, latest-staging, | ||
| # latest-production once triggered from those branches) | ||
| - name: Build and push | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: . | ||
| file: docker/Dockerfile | ||
| push: true | ||
| # build-push-action v6 enables these by default, which each push a | ||
| # separate untagged provenance/SBOM manifest to GHCR alongside the | ||
| # real image - not needed here, so turned off to keep the package | ||
| # version list clean. | ||
| provenance: false | ||
| sbom: false | ||
| tags: | | ||
| ${{ steps.meta.outputs.image }}:build-${{ github.run_number }} | ||
| ${{ steps.meta.outputs.image }}:sha-${{ steps.meta.outputs.sha_short }} | ||
| ${{ steps.meta.outputs.image }}:latest-${{ steps.meta.outputs.branch }} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # Stage 1: Build the WAR file using Maven | ||
| FROM maven:3.9-eclipse-temurin-21-alpine AS build | ||
| WORKDIR /app | ||
|
tmy1313 marked this conversation as resolved.
|
||
|
|
||
| # Copy the pom.xml files first to leverage Docker layer caching | ||
| # This ensures that if only source code changes, dependencies are not re-downloaded | ||
| COPY chpl/pom.xml . | ||
| COPY chpl/chpl-api/pom.xml chpl-api/ | ||
| COPY chpl/chpl-resources/pom.xml chpl-resources/ | ||
| COPY chpl/chpl-service/pom.xml chpl-service/ | ||
|
|
||
| # Copy the rest of the project files | ||
| COPY chpl/chpl-api/lombok.config chpl-api/lombok.config | ||
| COPY chpl/chpl-api/src chpl-api/src | ||
| COPY chpl/chpl-resources/src chpl-resources/src | ||
| COPY chpl/chpl-service/lombok.config chpl-service/lombok.config | ||
| COPY chpl/chpl-service/src chpl-service/src | ||
|
|
||
| RUN mvn clean package -DskipTests | ||
|
|
||
| # Stage 2: Deploy to Tomcat | ||
| # | ||
| # This image contains no secrets and is identical across every environment | ||
| # (dev/qa/stage/production). Tomcat config below only has ${ENV_VAR} | ||
| # placeholders (resolved at container startup - see catalina.properties' | ||
| # org.apache.tomcat.util.digester.PROPERTY_SOURCE) and the checked-in | ||
| # environment.properties/email.properties already mark every sensitive key | ||
| # as SECRET, relying on Spring's Environment to prefer OS environment | ||
| # variables over those classpath files. | ||
| # | ||
| # Required environment variables at `docker run` time: | ||
| # DB_URL, DB_USERNAME, DB_PASSWORD - jdbc/openchpl datasource | ||
| # plus every property marked SECRET in | ||
| # chpl/chpl-resources/src/main/resources/environment.properties and email.properties | ||
| # (e.g. SPRING_REDIS_PASSWORD, COGNITO_SECRETKEY, AZURE_CLIENTSECRET_ONC, JIRA_PASSWORD, ...) | ||
| FROM tomcat:11.0.23-jdk21 | ||
|
|
||
| COPY docker/tomcat-conf/server.xml /usr/local/tomcat/conf/server.xml | ||
| COPY docker/tomcat-conf/context.xml /usr/local/tomcat/conf/context.xml | ||
| COPY docker/tomcat-conf/catalina.properties /usr/local/tomcat/conf/catalina.properties | ||
|
|
||
| COPY --from=build /app/chpl-api/target/chpl-service.war /usr/local/tomcat/webapps/chpl-service.war | ||
|
|
||
| # Expose our custom Tomcat port | ||
| EXPOSE 8181 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| # Running the chpl-api Docker image | ||
|
|
||
| `docker/Dockerfile` builds a **secret-free** image: the same image is used for | ||
| every environment (development/qa/staging/production). Nothing sensitive is | ||
| baked in at build time - all of it is supplied as container environment | ||
| variables when the image is actually run. See `docker/Dockerfile` and | ||
| `docker/tomcat-conf/` for how that works mechanically (Tomcat's | ||
| `EnvironmentPropertySource` for `server.xml`, Spring's `Environment` for | ||
| everything else). | ||
|
|
||
| This doc lists every environment variable the image needs or accepts. It does | ||
| **not** contain real values for any environment - only what each variable is | ||
| for and what kind of value it expects. Real values for existing environments | ||
| currently live in [AudaciousInquiry/chpl-build](https://github.com/AudaciousInquiry/chpl-build) | ||
| (`chpl-build-{dev,qa,stg,prod}/src/main/resources/override-api-properties*.sh`) | ||
| - that repo should stay private, and its values should never be copied into | ||
| this one. | ||
|
|
||
| ## Quick start | ||
|
|
||
| ```sh | ||
| docker run -d --name chpl-api \ | ||
| -p 8181:8181 \ | ||
| -e DB_URL="jdbc:postgresql://<host>:5432/openchpl" \ | ||
| -e DB_USERNAME="<db-username>" \ | ||
| -e DB_PASSWORD="<db-password>" \ | ||
| -e chplUrlBegin="https://chpl-dev.healthit.gov" \ | ||
| -e SPRING_REDIS_HOST="<redis-host>" \ | ||
| -e SPRING_REDIS_PORT="6379" \ | ||
| -e SPRING_REDIS_PASSWORD="<redis-password>" \ | ||
| ghcr.io/<owner>/chpl-api:latest-development | ||
| ``` | ||
|
|
||
| Add `-e` flags for whichever of the feature-area variables below apply to | ||
| your environment - omitted ones just leave that feature unconfigured. | ||
|
|
||
| Note: property keys that contain dots (like `spring.redis.host`) are **not** | ||
| valid POSIX environment variable names on every shell/platform - Spring will | ||
| also match the all-caps/underscore form (`SPRING_REDIS_HOST`). Use whichever | ||
| form your deployment tooling handles more easily; both resolve to the same | ||
| property. | ||
|
|
||
| ## Required to start at all | ||
|
|
||
| | Env var | Used for | | ||
| |---|---| | ||
| | `DB_URL` | JDBC URL for the `jdbc/openchpl` datasource (`server.xml`) | | ||
| | `DB_USERNAME` | DB username (`server.xml`) | | ||
| | `DB_PASSWORD` | DB password (`server.xml`) | | ||
|
|
||
| ## Filesystem paths (need a mounted volume, not just an env var) | ||
|
|
||
| These properties are file/directory paths the app reads or writes at runtime. | ||
| Mount a volume at the path you set, or the app will fail writing to a | ||
| read-only container filesystem. | ||
|
|
||
| | Env var | Property | Purpose | | ||
| |---|---|---| | ||
| | `downloadFolderPath` | `downloadFolderPath` | Where generated downloadable files are written | | ||
| | `auditDataFilePath` | `auditDataFilePath` | Where audit data backups are written | | ||
|
|
||
| ## Environment-dependent (not secret, but should differ per environment) | ||
|
|
||
| | Env var | Property | Purpose | Example shape | | ||
| |---|---|---|---| | ||
| | `chplUrlBegin` | `chplUrlBegin` | Public base URL for this environment | `https://chpl-qa.healthit.gov` | | ||
| | `EMAILBUILDER_CONFIG_EMAILSUBJECTSUFFIX` | `emailBuilder.config.emailSubjectSuffix` | Tag appended to outgoing email subjects | `[QA]` | | ||
| | `SERVER_ENVIRONMENT` | `server.environment` | `non-production` or `production` | | | ||
| | `REPORT_ENVIRONMENT` | `report.environment` | Label used on generated reports | `DEV`, `QA`, `STAGE`, `PROD` | | ||
|
|
||
| ## Feature-area secrets | ||
|
|
||
| Every property below is marked `SECRET` in | ||
| [`environment.properties`](../chpl/chpl-resources/src/main/resources/environment.properties) | ||
| or [`email.properties`](../chpl/chpl-resources/src/main/resources/email.properties) | ||
| - meaning the app has no usable default and one of these env vars must be set | ||
| for that feature to work. If a feature isn't used in a given environment, its | ||
| variables can be omitted. | ||
|
|
||
| **Database / cache** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `SPRING_REDIS_HOST` | `spring.redis.host` | | ||
| | `SPRING_REDIS_PORT` | `spring.redis.port` | | ||
| | `SPRING_REDIS_PASSWORD` | `spring.redis.password` | | ||
|
|
||
| **AWS Cognito (authentication)** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `COGNITO_ACCESSKEY` | `cognito.accessKey` | | ||
| | `COGNITO_SECRETKEY` | `cognito.secretKey` | | ||
| | `COGNITO_REGION` | `cognito.region` | | ||
| | `COGNITO_USERPOOLID` | `cognito.userPoolId` | | ||
| | `COGNITO_USERPOOLCLIENTSECRET` | `cognito.userPoolClientSecret` | | ||
| | `COGNITO_CLIENTID` | `cognito.clientId` | | ||
| | `COGNITO_ENVIRONMENT_GROUPNAME` | `cognito.environment.groupName` | | ||
| | `COGNITO_SYSTEMUSERUUID` | `cognito.systemUserUuid` | | ||
| | `COGNITO_ANONYMOUSUSERUUID` | `cognito.anonymousUserUuid` | | ||
|
|
||
| **ONC Azure AD** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `AZURE_USER_ONC` | `azure.user.onc` | | ||
| | `AZURE_CLIENTID_ONC` | `azure.clientId.onc` | | ||
| | `AZURE_CLIENTSECRET_ONC` | `azure.clientSecret.onc` | | ||
| | `AZURE_TENANTID_ONC` | `azure.tenantId.onc` | | ||
|
|
||
| **JIRA** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `JIRA_USERNAME` | `jira.username` | | ||
| | `JIRA_PASSWORD` | `jira.password` | | ||
|
|
||
| **Datadog** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `DATADOG_APIKEY` | `datadog.apiKey` | | ||
| | `DATADOG_APPKEY` | `datadog.appKey` | | ||
|
|
||
| **AIA (Real World Testing validation)** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `AIA_AUTHENTICATE_CLIENTSECRET` | `aia.authenticate.clientSecret` | | ||
| | `AIA_AUTHENTICATE_CLIENTID` | `aia.authenticate.clientId` | | ||
|
|
||
| **FF4J admin console** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `FF4J_WEBCONSOLE_USERNAME` | `ff4j.webconsole.username` | | ||
| | `FF4J_WEBCONSOLE_PASSWORD` | `ff4j.webconsole.password` | | ||
|
|
||
| **Email / notifications** | ||
| | Env var | Property | | ||
| |---|---| | ||
| | `internalErrorEmailRecipients` | `internalErrorEmailRecipients` | | ||
| | `internalFutureCertificationStatusEmailRecipients` | `internalFutureCertificationStatusEmailRecipients` | | ||
| | `emailBuilder_config_forwardAddress` | `emailBuilder_config_forwardAddress` | | ||
| | `DIRECTREVIEW_CHPLCHANGES_EMAIL` | `directReview.chplChanges.email` | | ||
| | `DIRECTREVIEW_UNKNOWNCHANGES_EMAIL` | `directReview.unknownChanges.email` | | ||
|
|
||
| ## Anything not listed here | ||
|
|
||
| `environment.properties`, `email.properties`, `lookup.properties`, and | ||
| `errors.properties` (all in `chpl/chpl-resources/src/main/resources/`) have | ||
| sensible non-secret defaults for everything else, and can still be overridden | ||
| the same way (env var name = property name, dots -> underscores, upper-cased) | ||
| if a particular deployment needs to tune something not listed above. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I think we want to get to PROD eventually, I'd like to make sure we don't touch PROD at all until we're comfortable with the lower environments, so can we take this branch out of the list for now?