Docker cache #2666
This file contains 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
name: build | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.head_ref || (github.ref == 'refs/heads/main' && github.sha) || github.ref }} | |
cancel-in-progress: true | |
on: | |
workflow_dispatch: | |
push: | |
branches: | |
- main | |
pull_request: | |
branches: | |
- main | |
jobs: | |
#------------------------------------------------------ | |
# Setup values which is going to be used in other jobs | |
#------------------------------------------------------ | |
setup: | |
name: setup | |
runs-on: ubuntu-latest | |
outputs: | |
skip_ci: ${{ steps.check-ci-skip.outputs.skip_ci }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Get the head commit message | |
id: commit-message | |
run: | | |
head_commit_message=$(git log -1 --no-merges --pretty=%B | tr '\n' ' ' | sed "s/'/'\\\\''/g") | |
echo head commit message: $head_commit_message | |
echo "message=$head_commit_message" >> $GITHUB_OUTPUT | |
- name: Check for ci skip tags | |
id: check-ci-skip | |
run: | | |
commit_message='${{ steps.commit-message.outputs.message }}' | |
pr_title='${{ github.event.pull_request.title }}' | |
skip_tags=('[ci ignore]' '[ignore ci]') | |
echo "Checking commit message and pr title for ci skip tags..." | |
skip_ci="false" | |
for tag in "${skip_tags[@]}"; do | |
if [[ "$commit_message" == *"$tag"* ]] || [[ "$pr_title" == *"$tag"* ]]; then | |
echo "Found ci skip tag '$tag'." | |
echo "skip_ci=true" >> $GITHUB_OUTPUT | |
skip_ci="true" | |
break | |
fi | |
done | |
if [[ "$skip_ci" == "false" ]]; then | |
echo "No ci skip tag found." | |
echo "skip_ci=false" >> $GITHUB_OUTPUT | |
fi | |
#-------------------------------------------------- | |
# Build and Tests the project on Windows | |
#-------------------------------------------------- | |
tests-windows: | |
name: tests-windows | |
runs-on: windows-latest | |
timeout-minutes: 20 | |
steps: | |
- name: 'Setup: checkout project' | |
uses: actions/checkout@v4 | |
- name: 'Setup: environment' | |
id: setup | |
uses: ./.github/actions/setup | |
- name: 'Init: cache local Maven repository' | |
uses: actions/cache@v4 | |
with: | |
path: ~/.m2/repository | |
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} | |
restore-keys: | | |
${{ runner.os }}-maven- | |
- name: 'Init: install Node.js packages' | |
run: npm ci | |
- name: 'Test: run backend tests' | |
env: | |
DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} | |
run: | | |
./mvnw clean verify | |
#-------------------------------------------------- | |
# Build and Tests the project on Linux | |
#-------------------------------------------------- | |
tests-linux: | |
name: tests-linux | |
needs: [setup] | |
runs-on: ubuntu-latest | |
timeout-minutes: 20 | |
if: >- | |
needs.setup.outputs.skip_ci != 'true' | |
steps: | |
- name: 'Setup: checkout project' | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: 'Setup: environment' | |
id: setup | |
uses: ./.github/actions/setup | |
- name: 'Init: cache local Maven repository' | |
uses: actions/cache@v4 | |
with: | |
path: ~/.m2/repository | |
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} | |
restore-keys: | | |
${{ runner.os }}-maven- | |
- name: 'Start local Sonar' | |
run: docker compose -f src/main/docker/sonar.yml up -d | |
- name: 'Init: install Node.js packages' | |
run: npm ci | |
- name: 'Lint: check' | |
run: npm run lint:ci | |
- name: 'TEMP: enable gradle build tool slug' | |
run: sed -i '/- gradle-java/d' src/main/resources/config/application.yml | |
- name: 'Test: run backend tests' | |
env: | |
DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} | |
run: | | |
chmod +x mvnw | |
./mvnw clean verify -Dsonar.qualitygate.wait=true sonar:sonar | |
- name: 'Analysis: local Sonar' | |
run: | | |
./tests-ci/sonar.sh | |
- name: 'Analysis: SonarCloud' | |
if: github.repository == 'jhipster/jhipster-lite' && github.ref == 'refs/heads/main' | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any | |
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
run: ./mvnw initialize sonar:sonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.projectKey=jhipster_jhipster-lite -Dsonar.organization=jhipster -Dsonar.login= -Dsonar.password= | |
- name: 'Artifact: remove unused JARs' | |
run: | | |
rm target/*-javadoc.jar target/*-sources.jar | |
- name: 'Artifact: upload JAR' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: jhlite-jar | |
path: '${{ github.workspace }}/target/*.jar' | |
retention-days: 1 | |
#------------------------------------------------------ | |
# Build and Upload *.jar from main branch on Linux | |
#------------------------------------------------------ | |
generate-main-branch-jar: | |
name: generate-main-branch-jar | |
needs: [setup] | |
runs-on: ubuntu-latest | |
timeout-minutes: 20 | |
if: >- | |
needs.setup.outputs.skip_ci != 'true' && | |
github.event_name == 'pull_request' | |
steps: | |
- name: 'Setup: checkout project' | |
uses: actions/checkout@v4 | |
with: | |
ref: 'main' | |
fetch-depth: 0 | |
- name: 'Setup: environment' | |
id: setup | |
uses: ./.github/actions/setup | |
- name: 'Init: cache local Maven repository' | |
uses: actions/cache@v4 | |
with: | |
path: ~/.m2/repository | |
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} | |
restore-keys: | | |
${{ runner.os }}-maven- | |
- name: 'Init: install Node.js packages' | |
run: npm ci | |
- name: 'Lint: check' | |
run: npm run lint:ci | |
- name: 'TEMP: enable gradle build tool slug' | |
run: sed -i '/- gradle-java/d' src/main/resources/config/application.yml | |
- name: 'Build application JAR' | |
run: | | |
chmod +x mvnw | |
./mvnw clean package -DskipTests | |
- name: 'Artifact: upload JAR' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: jhlite-main-jar | |
path: '${{ github.workspace }}/target/*.jar' | |
retention-days: 1 | |
#-------------------------------------------------- | |
# Cypress | |
#-------------------------------------------------- | |
cypress: | |
needs: [tests-linux] | |
runs-on: ubuntu-latest | |
timeout-minutes: 10 | |
steps: | |
- name: 'Setup: checkout project' | |
uses: actions/checkout@v4 | |
- name: 'Setup: environment' | |
id: setup | |
uses: ./.github/actions/setup | |
- name: 'Artifact: download JAR' | |
uses: actions/download-artifact@v4 | |
with: | |
name: jhlite-jar | |
path: ./tests-ci/ | |
- name: 'Init: install Node.js packages' | |
run: npm ci | |
- name: 'Test: start application JHipster Lite' | |
working-directory: ./tests-ci/ | |
run: | | |
./start.sh 7471 | |
- name: 'Test: launch Cypress' | |
run: npm run e2e:headless | |
#-------------------------------------------------- | |
# Tests generated projects | |
#-------------------------------------------------- | |
generation: | |
needs: [setup, tests-linux, generate-main-branch-jar] | |
runs-on: ubuntu-latest | |
timeout-minutes: 10 | |
if: >- | |
!cancelled() && | |
needs.setup.outputs.skip_ci != 'true' && | |
needs.tests-linux.result == 'success' && | |
(needs.generate-main-branch-jar.result == 'success' || | |
needs.generate-main-branch-jar.result == 'skipped') | |
strategy: | |
matrix: | |
app: | |
- fullapp | |
- oauth2app | |
- mysqlapp | |
- mariadbapp | |
- mssqlapp | |
- flywayapp | |
- undertowapp | |
- eurekaapp | |
- consulapp | |
- gatewayapp | |
- mongodbapp | |
- redisapp | |
- cassandraapp | |
- neo4japp | |
- angularapp | |
- reactapp | |
- vueapp | |
- kafkaapp | |
- pulsarapp | |
- reactiveapp | |
- angularoauth2app | |
- customjhlite | |
- typescriptapp | |
- gradleapp | |
- thymeleafapp | |
include: | |
- java-build-tool: maven | |
- spring-config-format: yaml | |
- java-version: 21 | |
- node-version: 'lts/*' | |
- app: mariadbapp | |
spring-config-format: properties | |
- app: consulapp | |
java-version: 22 | |
- app: vueapp | |
node-version: 'latest' | |
- app: gradleapp | |
java-build-tool: gradle | |
steps: | |
- name: 'Setup: checkout project from main branch' | |
if: github.event_name == 'pull_request' | |
uses: actions/checkout@v4 | |
with: | |
ref: 'main' | |
path: 'main-branch' | |
- name: 'Setup: environment from main branch' | |
if: github.event_name == 'pull_request' | |
id: setup-main | |
uses: ./main-branch/.github/actions/setup | |
- name: 'Artifact: download JAR from main branch' | |
if: github.event_name == 'pull_request' | |
uses: actions/download-artifact@v4 | |
with: | |
name: jhlite-main-jar | |
path: ./main-branch/tests-ci/ | |
- name: 'Generation: generate ${{ matrix.app }} from main branch' | |
if: github.event_name == 'pull_request' | |
working-directory: ./main-branch/tests-ci/ | |
run: | | |
./start.sh 7471 | |
./generate.sh ${{ matrix.app }} ${{ matrix.java-build-tool }} ${{ matrix.spring-config-format }} | |
./stop.sh | |
- name: 'Generation: calculate md5sum ${{ matrix.app }} from main branch' | |
if: github.event_name == 'pull_request' | |
id: calculate-md5sum-main | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
app_md5=$(find . \ | |
-not -path './.git/*' \ | |
-not -path './.github/*' \ | |
-not -path './.jhipster/*' \ | |
-not -path './node_modules/*' \ | |
-not -path './target/*' \ | |
-not -path './build/*' \ | |
-type f -exec md5sum {} + | LC_ALL=C sort | md5sum | head -n1 | cut -d " " -f1) | |
echo main branch hash from project ${{ matrix.app }} $app_md5 | |
echo "hash=$app_md5" >> $GITHUB_OUTPUT | |
ls -al /tmp/jhlite/${{ matrix.app }} | |
- name: 'Clean: delete ${{ matrix.app }} from main branch' | |
if: github.event_name == 'pull_request' | |
run: | | |
rm -rf /tmp/jhlite/${{ matrix.app }} | |
- name: 'Setup: checkout project' | |
uses: actions/checkout@v4 | |
with: | |
path: 'current-branch' | |
- name: 'Setup: environment (java: ${{ matrix.java-version }}, node: ${{ matrix.node-version }})' | |
id: setup | |
uses: ./current-branch/.github/actions/setup | |
with: | |
java-version: ${{ matrix.java-version }} | |
node-version: ${{ matrix.node-version }} | |
- name: 'Artifact: download JAR' | |
uses: actions/download-artifact@v4 | |
with: | |
name: jhlite-jar | |
path: ./current-branch/tests-ci/ | |
- name: 'Generation: generate ${{ matrix.app }}' | |
working-directory: ./current-branch/tests-ci/ | |
run: | | |
./start.sh 7471 | |
./generate.sh ${{ matrix.app }} ${{ matrix.java-build-tool }} ${{ matrix.spring-config-format }} | |
./stop.sh | |
- name: 'Generation: calculate md5sum ${{ matrix.app }}' | |
id: calculate-md5sum | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
app_md5=$(find . \ | |
-not -path './.git/*' \ | |
-not -path './.github/*' \ | |
-not -path './.jhipster/*' \ | |
-not -path './node_modules/*' \ | |
-not -path './target/*' \ | |
-not -path './build/*' \ | |
-type f -exec md5sum {} + | LC_ALL=C sort | md5sum | head -n1 | cut -d " " -f1) | |
echo pull request branch hash from project ${{ matrix.app }} $app_md5 | |
echo "hash=$app_md5" >> $GITHUB_OUTPUT | |
ls -al /tmp/jhlite/${{ matrix.app }} | |
- name: 'Compare hash main x pull request ${{ matrix.app }}' | |
if: github.event_name == 'pull_request' | |
id: compare-hash | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
echo main branch hash from project ${{ matrix.app }} ${{ steps.calculate-md5sum-main.outputs.hash }} | |
echo pull request branch hash from project ${{ matrix.app }} ${{ steps.calculate-md5sum.outputs.hash }} | |
# Compare hashes | |
if [ "${{ steps.calculate-md5sum-main.outputs.hash }}" != "${{ steps.calculate-md5sum.outputs.hash }}" ]; then | |
echo "different=true" >> $GITHUB_OUTPUT | |
else | |
echo "different=false" >> $GITHUB_OUTPUT | |
fi | |
- name: 'Determine if tests are needed' | |
id: tests-requirement-check | |
run: | | |
if [[ "${{ steps.compare-hash.outputs.different }}" == "true" || "${{ steps.compare-hash.conclusion }}" == "skipped" ]]; then | |
echo "execute_tests=true" >> $GITHUB_OUTPUT | |
else | |
echo "execute_tests=false" >> $GITHUB_OUTPUT | |
fi | |
- name: 'Test: list ${{ matrix.app }}' | |
if: | | |
steps.tests-requirement-check.outputs.execute_tests == 'true' && | |
${{ matrix.java-build-tool }} == 'maven' | |
id: cache_maven_md5sum | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
ls -al | |
MD5SUM_POM_XML=$(md5sum pom.xml | cut -d ' ' -f 1) | |
echo $MD5SUM_POM_XML | |
echo "md5sum_pom_xml=${MD5SUM_POM_XML}" >> $GITHUB_OUTPUT | |
- name: 'Init: cache local Maven repository' | |
if: | | |
steps.tests-requirement-check.outputs.execute_tests == 'true' && | |
${{ matrix.java-build-tool }} == 'maven' | |
uses: actions/cache@v4 | |
with: | |
path: ~/.m2/repository | |
key: ${{ runner.os }}-${{ matrix.java-build-tool }}-${{ matrix.app }}-${{ steps.cache_maven_md5sum.outputs.md5sum_pom_xml }} | |
restore-keys: | | |
${{ runner.os }}-${{ matrix.java-build-tool }}- | |
- name: 'Test: list ${{ matrix.app }}' | |
if: | | |
steps.tests-requirement-check.outputs.execute_tests == 'true' && | |
${{ matrix.java-build-tool }} == 'gradle' | |
id: cache_gradle_md5sum | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
ls -al | |
GRADLE_DEPS_MD5=$(md5sum \ | |
build.gradle.kts \ | |
settings.gradle.kts \ | |
gradle/libs.versions.toml \ | |
gradle/wrapper/gradle-wrapper.properties \ | |
| md5sum | head -n1 | cut -d " " -f1) | |
echo $GRADLE_DEPS_MD5 | |
echo "md5sum=${GRADLE_DEPS_MD5}" >> $GITHUB_OUTPUT | |
- name: 'Init: cache local Gradle repository' | |
if: | | |
steps.tests-requirement-check.outputs.execute_tests == 'true' && | |
${{ matrix.java-build-tool }} == 'gradle' | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.gradle/caches | |
~/.gradle/wrapper | |
key: ${{ runner.os }}-${{ matrix.java-build-tool }}-${{ matrix.app }}-${{ steps.cache_gradle_md5sum.outputs.md5sum }} | |
restore-keys: | | |
${{ runner.os }}-${{ matrix.java-build-tool }}- | |
- name: 'Test: starting Sonar' | |
if: steps.tests-requirement-check.outputs.execute_tests == 'true' | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
if [ -f 'src/main/docker/sonar.yml' ]; then | |
docker compose -f src/main/docker/sonar.yml up -d | |
${{ github.workspace }}/current-branch/tests-ci/wait_sonar.sh | |
docker ps -a | |
fi | |
- name: 'Install jhlite snapshot jar in local maven repository' | |
if: steps.tests-requirement-check.outputs.execute_tests == 'true' | |
working-directory: ./current-branch/ | |
run: | | |
export JHLITE_VERSION=$(find tests-ci -maxdepth 1 -name "*-tests.jar" | sed -e 's/.*jhlite-\(.*\)-tests\.jar/\1/') | |
echo "JHLITE_VERSION=${JHLITE_VERSION}" | |
./mvnw install:install-file -Dfile=tests-ci/jhlite-${JHLITE_VERSION}.jar -DgroupId=tech.jhipster.lite -DartifactId=jhlite -Dversion=${JHLITE_VERSION} | |
./mvnw install:install-file -Dfile=tests-ci/jhlite-${JHLITE_VERSION}-tests.jar -DgroupId=tech.jhipster.lite -DartifactId=jhlite -Dversion=${JHLITE_VERSION} -Dclassifier=tests | |
- name: 'Test: verify ${{ matrix.app }}' | |
if: steps.tests-requirement-check.outputs.execute_tests == 'true' | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
if [ -f 'mvnw' ]; then | |
./mvnw clean verify -Dsonar.qualitygate.wait=true sonar:sonar | |
elif [ -f 'gradlew' ]; then | |
./gradlew clean build sonar --no-daemon --info | |
else | |
npm install | |
npm test | |
fi | |
- name: 'Test: check local Sonar Analysis' | |
if: steps.tests-requirement-check.outputs.execute_tests == 'true' | |
run: | | |
if [ -f '/tmp/jhlite/${{ matrix.app }}/src/main/docker/sonar.yml' ]; then | |
./current-branch/tests-ci/sonar.sh ${{ matrix.app }} | |
fi | |
- name: 'Test: copy shell scripts' | |
if: steps.tests-requirement-check.outputs.execute_tests == 'true' | |
run: cp ./current-branch/tests-ci/start.sh /tmp/jhlite/${{ matrix.app }}/ | |
- name: 'Test: start docker-compose services' | |
if: steps.tests-requirement-check.outputs.execute_tests == 'true' | |
working-directory: ./current-branch/tests-ci/ | |
run: | | |
./start_docker_compose.sh /tmp/jhlite/${{ matrix.app }}/ | |
- name: 'Test: start the application' | |
if: steps.tests-requirement-check.outputs.execute_tests == 'true' | |
working-directory: /tmp/jhlite/${{ matrix.app }}/ | |
run: | | |
# TODO: add also 'gradlew' once gradle support is more advanced | |
if [ -f 'mvnw' ]; then | |
./start.sh | |
fi | |
#-------------------------------------------------- | |
# Configuration for Status checks that are required | |
#-------------------------------------------------- | |
status-checks: | |
name: status-checks | |
needs: [tests-linux, generation] | |
permissions: | |
contents: none | |
if: always() | |
runs-on: ubuntu-latest | |
timeout-minutes: 5 | |
steps: | |
- name: Validation Status checks | |
run: | | |
echo 'Configuration for Status checks that are required' | |
echo '${{ toJSON(needs) }}' | |
if [[ (('skipped' == '${{ needs.tests-linux.result }}') || ('success' == '${{ needs.tests-linux.result }}')) && (('skipped' == '${{ needs.generation.result }}') || ('success' == '${{ needs.generation.result }}')) ]]; then | |
exit 0 | |
fi | |
exit 1 | |
#-------------------------------------------------- | |
# Dependabot auto merge PR | |
#-------------------------------------------------- | |
dependabot-auto-merge: | |
name: dependabot-auto-merge | |
needs: [cypress, generation] | |
permissions: | |
pull-requests: write | |
contents: write | |
runs-on: ubuntu-latest | |
if: ${{ github.repository == 'jhipster/jhipster-lite' && github.ref != 'refs/heads/main' && github.event.pull_request.user.login == 'dependabot[bot]' }} | |
steps: | |
- name: Dependabot metadata | |
id: dependabot-metadata | |
uses: dependabot/fetch-metadata@v2.1.0 | |
- name: Enable auto-merge for Dependabot PRs | |
if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }} | |
run: gh pr merge --auto --merge "$PR_URL" | |
env: | |
PR_URL: ${{ github.event.pull_request.html_url }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |