Skip to content

COMMIT STAGE - Java codes build & quality verification #25

COMMIT STAGE - Java codes build & quality verification

COMMIT STAGE - Java codes build & quality verification #25

# Main COMMIT STAGE workflow regarding the java projects managed via Maven tool
name: Java Project CI (COMMIT STAGE)
run-name: COMMIT STAGE - Java codes build & quality verification
on:
push:
# execution when development java source codes commit is pushed by a developer of a feature, hotfix, or fix branch
branches:
- 'feature*'
- 'hotfix*'
- 'fix*'
# execute only when changes detected on files or java sub-projects contents
# becarefull, path filters are not evaluated on tags
paths:
- 'pom.xml'
- 'implementations-line/**'
- 'systems-line/**'
- '.github/workflows/java-project-ci.yml'
- '.github/workflows/check-project-technical-quality.yml'
- '.github/workflows/publish-java-packages-version-to-repository.yml'
- '!**/*.md'
# execute when a alpha tag is added on the feature branch as "finished work" (e.g by developer)
tags:
- '[0-9]+.[0-9]+.[0-9]+-*'
- '*-reviewed'
- 'reviewed*'
- '*-alpha'
pull_request:
# execution when pull request is requested by a developer (e.g to reviewer) on his development branch or another branch
types: [opened, reopened, review_requested]
branches:
- 'feature*'
- 'hotfix*'
- 'fix*'
# execute only when reviewed files or java sub-projects
paths:
- 'pom.xml'
- 'implementations-line/**'
- 'systems-line/**'
pull_request_target:
# when a pull request merges, the pull request is automatically closed (so check the merged state)
types: [closed]
# execution when feature's artifacts (e.g implementation doc, java source code) were reviewed
branches:
- 'feature*'
- 'hotfix*'
- 'fix*'
# execute only when reviewed files or java sub-projects
paths:
- 'pom.xml'
- 'implementations-line/**'
- 'systems-line/**'
# The commit stage workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
define_project_release_name:
name: Release name preparation
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
release_name: ${{ env.release_name }}
is_snapshot: ${{ env.is_snapshot }}
latest_release_name: ${{ env.latest_release_name }}
steps:
- name: Check existing project defined version name
if: ${{ github.event.release.tag_name != '' }}
# Read the release name defined into the GitHub project
run: |
echo The current release tag is ${{ github.event.release.tag_name }}
echo "TAG_VERSION=${{ github.event.release.tag_name }}" >> $GITHUB_ENV
echo "is_snapshot=${{ contains(github.event.release.tag_name, 'snapshot') || contains(github.event.release.tag_name, 'reviewed') }}" >> $GITHUB_ENV
- name: Set the release name of the project based on GitHub tag name
if: ${{ env.TAG_VERSION != '' }}
run : |
echo "Define the final version identifier from the GitHub project's current tag name"
echo "release_name=$TAG_VERSION" >> $GITHUB_ENV
echo "Development version type is detected from the GitHub tag name as ${{ env.is_snapshot }}"
# Build specific release name because none tag is existing on GitHub project
- name: Define reusable environment variables about current commit
if: ${{ env.TAG_VERSION == '' }}
uses: FranzDiebold/github-env-vars-action@v2
- name: Define an unique revision name (pattern <<feature branch name>>.<<commit id abbrev>>) regarding development release
if: ${{ env.TAG_VERSION == '' }}
run: |
echo "Git commit revision $CI_SHA_SHORT abbreviation based on 7 characters (default) maximum (origin based: $CI_SHA)"
echo "COMMIT_ID=$CI_SHA_SHORT" >> $GITHUB_ENV
echo "FEATURE_NAME=$CI_ACTION_REF_NAME_SLUG" >> $GITHUB_ENV
echo "is_snapshot=true" >> $GITHUB_ENV
echo "Development version type is defined as snapshot based on $CI_SHA_SHORT commit revision number"
- name: Define a snapshot feature name (based on unique commit id) and latest version name
# Build final name about featureX name, but avoiding COMMIT_ID and SNAPSHOT suffix
if: ${{ env.TAG_VERSION == '' && ( !contains(env.FEATURE_NAME, 'alpha') && !contains(env.FEATURE_NAME, 'reviewed') ) }}
# Build unique name including commit_id suffix based
# Example of output name: feature-133.9efbb506-SNAPSHOT
# Example of latest version name: feature-133-SNAPSHOT
run: |
echo "release_name=$FEATURE_NAME.$COMMIT_ID-SNAPSHOT" >> $GITHUB_ENV
echo "latest_release_name=$FEATURE_NAME-SNAPSHOT" >> $GITHUB_ENV
- name: Set a snapshot reviewed version name of the project based on CYBNITY versioning strategy
# Build final name about any tag named branch (maybe don't include feature name including -reviewed or -alpha)
if: ${{ env.TAG_VERSION == '' && env.release_name == '' }}
# Build name based on a potential included tag (e.g 0.0.7-reviewed, 0.0.7-alpha, 0.0.7) without commit_id suffix
# Example of output name 0.0.7-reviewed-SNAPSHOT, feature133-alpha-SNAPSHOT
run: echo "release_name=$FEATURE_NAME-SNAPSHOT" >> $GITHUB_ENV
binary_build:
name: Java components build & test
if: success() && github.event_name == 'push'
needs: [define_project_release_name]
runs-on: ubuntu-latest
permissions:
contents: read
env:
RELEASE_NAME: ${{ needs.define_project_release_name.outputs.release_name }}
DOCKER_REGISTRY_USERNAME: ${{ secrets.DOCKER_REGISTRY_ACCESS_ACCOUNT }}
DOCKER_REGISTRY_PASSWORD: ${{ secrets.DOCKER_REGISTRY_ACCESS_TOKEN }}
MAVEN_USERNAME: ${{ secrets.AGNET_REPO_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.AGNET_REPO_PASSWORD }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
GITHUB_TOKEN: ${{ github.token }} # GITHUB_TOKEN is the default env for the password
outputs:
release_name: ${{ env.RELEASE_NAME }}
steps:
- name: Checkout source codes from branch
id: checkout_step
uses: actions/checkout@v4
with:
repository: ${{ github.repository }}
token: ${{ github.token }}
ref: ${{ inputs.branch_name }}
- name: Set up java runtime (Temurin JDK)
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'temurin'
cache: maven
# defined settings.xml values allowing use of CYBNITY Maven remote repository
server-id: agnet
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value (without an modification than exported by the gpg --export-secret-keys command) of the GPG private key (33105BFD367D25B3) to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: Install gpg secret key used for artefacts signing
run: |
# Install gpg secret key
cat <(echo -e "${{ secrets.MAVEN_GPG_PRIVATE_KEY }}") | gpg --batch --import
# Verify gpg secret key
gpg --list-secret-keys --keyid-format LONG
- name: Validate all necessary information and compile source code
run: |
echo "Set the project artifacts version in pom files"
mvn -B -DgenerateBackupPoms=true -DprocessAllModules=true versions:set -DnewVersion=${{ env.RELEASE_NAME }}
echo "Execute the java project(s) build via Maven tool"
mvn --batch-mode --update-snapshots --show-version -Drevision=${{ env.RELEASE_NAME }} --fail-fast --file pom.xml -Dstage=commit clean compile -Dmaven.test.skip=true
- name: Execute unit tests validating the java compiled source code
run: |
echo "Compile unit tests and java project(s), and execute tests via Maven tool"
mvn --batch-mode --update-snapshots --show-version -Drevision=${{ env.RELEASE_NAME }} -Dmaven.test.skip=false --fail-fast --file pom.xml -Dstage=commit test
- name: Package compiled java code in its distributable format (e.g JAR, Docker image)
run: |
mvn --batch-mode --update-snapshots --show-version -Drevision=${{ env.RELEASE_NAME }} -Ddocker.username=${{ env.DOCKER_REGISTRY_USERNAME }} -Ddocker.password=${{ env.DOCKER_REGISTRY_PASSWORD }} -Ddocker.cleanup=none --fail-fast --file pom.xml -Dstage=commit package -Dmaven.test.skip=true
- name: Verify packaged components
run: |
echo "Run any checks to verify the package is valid and meets quality criteria (including test resources) without unit test execution"
mvn -Drevision=${{ env.RELEASE_NAME }} --batch-mode --update-snapshots --show-version -Ddocker.username=${{ env.DOCKER_REGISTRY_USERNAME }} -Ddocker.password=${{ env.DOCKER_REGISTRY_PASSWORD }} -Ddocker.cleanup=none --fail-fast --file pom.xml -Dstage=commit verify -DskipTests
# Verify the technical quality of the version
check_technical_quality:
name: Technical quality check
if: success() && github.event_name == 'push'
needs: [binary_build]
uses: ./.github/workflows/check-project-technical-quality.yml
with:
config-path: ${{ needs.binary_build.steps.checkout_step.ref }}
package_release_name: ${{ needs.binary_build.outputs.release_name }}
secrets: inherit
# Prepare a release for remote repository installation (published in place of old equals release name in remote repository, reviewed or not)
# Publish release of parent pom.xml and sub-projects (reusable by other development, or for processing by Automated Acceptance Test stage) that potentially replace previous equals version named
publish_version_to_release_remote_repository:
name: Release publishing
if: ${{ success() && needs.define_project_release_name.outputs.is_snapshot == 'false' }}
needs: [define_project_release_name, binary_build]
uses: ./.github/workflows/publish-java-packages-version-to-repository.yml
with:
config-path: ${{ needs.binary_build.steps.checkout_step.ref }}
target_repository: RELEASE
package_release_name: ${{ needs.binary_build.outputs.release_name }}
secrets: inherit
# Prepare only a snapshot version for remote repository installation
publish_tagged_version_to_snapshot_remote_repository:
name: Tagged snapshot version publishing
# By default, don't publish snapshot version on other repository than the local developer workstation's maven repository
# The Pull Request (PR) of development revision was approved and merged, but maybe work is not finished
# Publish TAGGED snapshot version (parent pom.xml and sub-projects available for other features' developers) on remote repository
# it's a development version publishable as 'snapshot'
# only when approved, merged and tagged as 'reviewed' (e.g by reviewer)
# or only when a reviewed tag is pushed only on the branch (e.g after a review already executed after closed PR)
# or only when a alpha tag is pushed only on the branch (e.g when feature developer or reviewer indicate that work is finished)
if: ${{ success()
&& needs.define_project_release_name.outputs.is_snapshot == 'true'
&& (
(github.event.pull_request.merged == true && github.event.pull_request.reviewDecision == 'approved')
||
( github.event_name == 'push' && github.ref_type == 'tag' && ( contains(github.ref_name, 'reviewed') || contains(github.ref_name, 'alpha') ))
)
}}
needs: [define_project_release_name, binary_build]
uses: ./.github/workflows/publish-java-packages-version-to-repository.yml
with:
config-path: ${{ needs.binary_build.steps.checkout_step.ref }}
target_repository: SNAPSHOT
package_release_name: ${{ needs.binary_build.outputs.release_name }}
secrets: inherit
# Prepare only a snapshot latest version for remote repository installation
publish_latest_version_to_snapshot_remote_repository:
name: Latest version publishing
# Publish not tagged snapshot version but as a common name equals to latest version of feature branche available for other domain application projects managed in other repositories
if: ${{ success()
&& needs.define_project_release_name.outputs.is_snapshot == 'true'
&& (github.event_name == 'push' && needs.define_project_release_name.outputs.latest_release_name != '' && contains(github.ref_name, 'feature'))
}}
needs: [define_project_release_name, binary_build]
uses: ./.github/workflows/publish-java-packages-version-to-repository.yml
with:
config-path: ${{ needs.binary_build.steps.checkout_step.ref }}
target_repository: SNAPSHOT
package_release_name: ${{ needs.define_project_release_name.outputs.latest_release_name }}
secrets: inherit