CI #575
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
--- | ||
# DO NOT EDIT: this file is automatically synced from the template repository | ||
# in https://github.com/Liber-UFPE/project-starter. | ||
name: CI | ||
# yamllint disable rule:truthy | ||
on: | ||
push: | ||
branches: [ "main" ] | ||
pull_request: | ||
types: [ "opened", "synchronize", "reopened" ] | ||
# yamllint enable rule:truthy | ||
env: | ||
REGISTRY: ghcr.io | ||
GRADLE_OPTS: > | ||
-Dorg.gradle.console=plain | ||
-Dorg.gradle.caching=true | ||
-Dsonar.gradle.skipCompile=true | ||
-Dorg.gradle.jvmargs="-Xmx2g -XX:MaxMetaspaceSize=512m"' | ||
concurrency: | ||
# This workflow cuts releases, so we want only a | ||
# single concurrent workflow run per branch/tag/etc. | ||
group: ${{ github.ref }} | ||
cancel-in-progress: true | ||
jobs: | ||
diktat: | ||
name: Code Analysis / diktat | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: marcospereira/kotlin-diktat-action@v1 | ||
with: | ||
patterns: "src/main/kotlin src/test/kotlin '!src/main/kotlin/br/ufpe/liber/tasks/*.kt'" | ||
ktlint: | ||
name: Code Analysis / ktlint | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: nbadal/action-ktlint-setup@v1 | ||
- run: ktlint --version | ||
- run: ktlint --relative >> $GITHUB_STEP_SUMMARY | ||
detekt: | ||
name: Code Analysis / detekt | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: detekt report | ||
uses: natiginfo/[email protected] | ||
with: | ||
args: | | ||
--report md:build/reports/detekt/detekt.md | ||
- name: Detekt Summary | ||
run: cat build/reports/detekt/detekt.md >> $GITHUB_STEP_SUMMARY | ||
stylelint: | ||
name: Code Analysis / stylelint | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- run: corepack enable | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: "lts/*" # latest lts | ||
check-latest: true | ||
cache: "yarn" | ||
- run: yarn install | ||
- run: npx stylelint src/main/**/*.scss | ||
eslint: | ||
name: Code Analysis / eslint | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- run: corepack enable | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: "lts/*" # latest lts | ||
check-latest: true | ||
cache: "yarn" | ||
- run: yarn install | ||
- run: npx eslint . | ||
esbuild-check: | ||
name: Test / Assets / pipeline | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
node-version: [ 20, 21 ] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- run: corepack enable | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
check-latest: true | ||
cache: "yarn" | ||
- run: node --version | ||
- run: corepack enable | ||
- run: yarn install | ||
- name: Run assets pipeline | ||
run: | | ||
rm -rf ./build | ||
node assets-pipeline.mjs | ||
tree ./build | ||
gradle-wrapper-validation: | ||
name: Gradle / wrapper-validation | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: gradle/actions/wrapper-validation@v3 | ||
validate-external-links: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Link Checker | ||
uses: lycheeverse/lychee-action@v1 | ||
with: | ||
args: '--verbose --no-progress --exclude-loopback --exclude-path node_modules **/*.md' | ||
jobSummary: true | ||
format: markdown | ||
fail: true | ||
compile: | ||
name: Build / compile | ||
runs-on: ubuntu-latest | ||
needs: | ||
- diktat | ||
- detekt | ||
- ktlint | ||
- stylelint | ||
- eslint | ||
- esbuild-check | ||
- gradle-wrapper-validation | ||
- validate-external-links | ||
- dependency-review | ||
Check failure on line 142 in .github/workflows/build.yml
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- run: corepack enable | ||
- name: Set up Gradle and Java | ||
uses: ./.github/gradle-action | ||
with: | ||
# Allows this job to write to the cache every time it runs | ||
gradle-cache-read-only: false | ||
- name: Start Gradle Daemon | ||
run: ./gradlew --info | ||
- run: ./gradlew testClasses | ||
dependency-review: | ||
runs-on: ubuntu-latest | ||
if: ${{ github.event_name == 'pull_request' }} | ||
needs: | ||
- compile | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: 'Dependency Review' | ||
uses: actions/dependency-review-action@v4 | ||
with: | ||
fail-on-severity: high | ||
fail-on-scopes: runtime | ||
test: | ||
name: Tests / test | ||
runs-on: ubuntu-latest | ||
needs: | ||
- compile | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
- run: corepack enable | ||
- name: Set up Gradle and Java | ||
uses: ./.github/gradle-action | ||
- name: Cache SonarCloud packages | ||
uses: actions/cache@v4 | ||
with: | ||
path: ~/.sonar/cache | ||
key: ${{ runner.os }}-sonar | ||
restore-keys: ${{ runner.os }}-sonar | ||
- name: Run tests | ||
run: ./gradlew check koverXmlReport | ||
- name: Run SonarCloud Analysis | ||
continue-on-error: true | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | ||
run: ./gradlew sonar | ||
- name: Buildkite Test Analytics | ||
if: ${{ github.ref == 'refs/heads/main' && always() }} | ||
env: | ||
BUILDKITE_ANALYTICS_TOKEN: ${{ secrets.BUILDKITE_ANALYTICS_TOKEN }} | ||
run: | | ||
./gradlew mergeJUnitReports | ||
COMMIT_MESSAGE=$(git log -n 1 --format="%s") | ||
curl -X POST --fail-with-body \ | ||
-H "Authorization: Token token=$BUILDKITE_ANALYTICS_TOKEN" \ | ||
-F "data=@build/test-results/junit.xml" \ | ||
-F "format=junit" \ | ||
-F "run_env[CI]=github_actions" \ | ||
-F "run_env[key]=$GITHUB_ACTION-$GITHUB_RUN_NUMBER-$GITHUB_RUN_ATTEMPT" \ | ||
-F "run_env[number]=$GITHUB_RUN_NUMBER" \ | ||
-F "run_env[branch]=$GITHUB_REF" \ | ||
-F "run_env[commit_sha]=$GITHUB_SHA" \ | ||
-F "run_env[message]=$COMMIT_MESSAGE" \ | ||
-F "run_env[url]=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ | ||
https://analytics-api.buildkite.com/v1/uploads | ||
- name: Upload coverage reports to Codecov | ||
uses: codecov/codecov-action@v4 | ||
continue-on-error: true | ||
env: | ||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | ||
with: | ||
verbose: true | ||
test-docker-image: | ||
name: Tests / docker image | ||
runs-on: ubuntu-latest | ||
needs: | ||
- compile | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: docker/setup-buildx-action@v3 | ||
- name: Docker / Get image name | ||
id: dockerImageName | ||
# yamllint disable rule:line-length | ||
# language="shell script" | ||
run: | | ||
echo "dockerImageName=${{ env.REGISTRY }}/${{ github.repository }}" | tr '[:upper:]' '[:lower:]'>> "$GITHUB_OUTPUT" | ||
- name: Create Image | ||
uses: docker/build-push-action@v6 | ||
with: | ||
context: . | ||
load: true # Load is a shorthand for --output=type=docker | ||
tags: ${{ steps.dockerImageName.outputs.dockerImageName }}:latest | ||
# See https://docs.docker.com/build/ci/github-actions/cache/#github-cache | ||
cache-from: type=gha | ||
cache-to: type=gha,mode=max | ||
build-args: | | ||
BUILDKIT_INLINE_CACHE=1 | ||
- name: Test Image | ||
run: | | ||
containerId=$(docker run -d --rm --publish 8080:8080 ${{ steps.dockerImageName.outputs.dockerImageName }}) | ||
wget --retry-connrefused --tries=20 -nv --wait=1 --spider http://localhost:8080/ | ||
docker container logs "$containerId" | ||
docker container stop "$containerId" | ||
- name: Generate image tar if release branch | ||
if: ${{ github.ref == 'refs/heads/main' }} | ||
# language="shell script" | ||
run: | | ||
docker save "${{ steps.dockerImageName.outputs.dockerImageName }}:latest" | gzip > generate-image-latest.tar.gz | ||
# yamllint enable rule:line-length | ||
- name: Upload image tar if release branch | ||
if: ${{ github.ref == 'refs/heads/main' }} | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
path: generate-image-latest.tar.gz | ||
# From GitHub Actions docs: https://docs.github.com/en/actions/learn-github-actions/contexts#github-context | ||
# github.run_id is a unique number for each workflow run within a repository. | ||
# This number does not change if you re-run the workflow run. | ||
# | ||
# It then makes sense to use this to name artifacts and have some guarantees that the name | ||
# is stable (per workflow) and unique (to avoid artifacts uploading name clashes). | ||
# | ||
# The same naming MUST be used when downloading the artifact later. See actions/upload-artifact migration | ||
# docs for more information: | ||
# https://github.com/actions/upload-artifact/blob/main/docs/MIGRATION.md#multiple-uploads-to-the-same-named-artifact | ||
name: docker-image-${{ github.run_id }} | ||
compression-level: 0 # No compression since it is already a gzip file | ||
good-to-merge: | ||
name: Good to merge | ||
runs-on: ubuntu-latest | ||
if: ${{ github.event_name == 'pull_request' }} | ||
needs: | ||
- test | ||
- test-docker-image | ||
- dependency-review | ||
steps: | ||
- run: echo "This PR is ready to merge." | ||
generate-tag-name: | ||
name: Generate GitHub tag name | ||
if: ${{ github.ref == 'refs/heads/main' }} | ||
runs-on: ubuntu-latest | ||
needs: | ||
- test | ||
- test-docker-image | ||
# This job also has an output that can be used by downstream jobs. | ||
# https://docs.github.com/en/actions/using-jobs/defining-outputs-for-jobs | ||
outputs: | ||
tagName: ${{ steps.generateTagName.outputs.tagName }} | ||
steps: | ||
- run: echo "This is a push to main branch. Following with release a new version" | ||
- name: Generate tag name | ||
id: generateTagName | ||
# TAG_NAME value is trying to emulate semver to avoid release ordering issues. | ||
# See https://github.com/orgs/community/discussions/8226. | ||
run: echo "tagName=v$(date '+%Y%m%d.%H%M.%S')" >> "$GITHUB_OUTPUT" | ||
create-release: | ||
name: Creates a GitHub Release | ||
runs-on: ubuntu-latest | ||
needs: | ||
- generate-tag-name | ||
# Docs: | ||
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs | ||
permissions: | ||
contents: write | ||
packages: read # to preserve default permissions | ||
env: | ||
GH_TOKEN: ${{ github.token }} | ||
TAG_NAME: ${{ needs.generate-tag-name.outputs.tagName }} | ||
RELEASE_TITLE: Release ${{ needs.generate-tag-name.outputs.tagName }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- run: corepack enable | ||
- uses: ./.github/gradle-action | ||
- name: Generate jar artifacts | ||
run: ./gradlew -PreleaseTag=$TAG_NAME clean shadowJar -x test -x accessibilityTest --no-configuration-cache | ||
- name: Create Github Release | ||
run: gh release create "$TAG_NAME" --title "$RELEASE_TITLE" --generate-notes --latest ./build/libs/*.jar | ||
publish-docker-image: | ||
name: Publish docker image | ||
runs-on: ubuntu-latest | ||
env: | ||
GH_TOKEN: ${{ github.token }} | ||
TAG_NAME: ${{ needs.generate-tag-name.outputs.tagName }} | ||
needs: | ||
- generate-tag-name | ||
permissions: | ||
contents: read | ||
packages: write | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 # 0 indicates all history for all branches and tags. | ||
- uses: docker/setup-buildx-action@v3 | ||
- name: Docker / Get image name | ||
id: dockerImageName | ||
# yamllint disable rule:line-length | ||
# language="shell script" | ||
run: | | ||
echo "dockerImageName=${{ env.REGISTRY }}/${{ github.repository }}" | tr '[:upper:]' '[:lower:]'>> "$GITHUB_OUTPUT" | ||
# yamllint enable rule:line-length | ||
- name: Download previously generated image tar | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: docker-image-${{ github.run_id }} | ||
- name: Create Image | ||
# language="shell script" | ||
run: | | ||
artifact_file="generate-image-latest.tar.gz" | ||
if [ -f "$artifact_file" ]; then | ||
echo "Previously generate image found. Will load image" | ||
docker load < "$artifact_file" | ||
else | ||
echo "Previously generate image NOT found. Will build image" | ||
docker image build -t ${{ steps.dockerImageName.outputs.dockerImageName }}:latest . | ||
fi | ||
# Needs to log in to use docker scout below | ||
- uses: docker/login-action@v3 | ||
with: | ||
username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
- uses: docker/scout-action@v1 | ||
continue-on-error: true | ||
with: | ||
command: quickview | ||
image: ${{ steps.dockerImageName.outputs.dockerImageName }} | ||
write-comment: false | ||
summary: true | ||
# Adapted from https://docs.docker.com/build/ci/github-actions/test-before-push/ | ||
- name: Test Image | ||
# From `docker run --help`: | ||
# -d, --detach Run container in background and print container ID | ||
# --rm Automatically remove the container when it exits | ||
# -p, --publish list Publish a container's port(s) to the host | ||
run: | | ||
containerId=$(docker run -d --rm --publish 8080:8080 ${{ steps.dockerImageName.outputs.dockerImageName }}) | ||
wget --retry-connrefused --tries=20 -nv --wait=1 --spider http://localhost:8080/ | ||
docker container logs "$containerId" | ||
docker container stop "$containerId" | ||
- name: Login to GitHub Container Registry | ||
uses: docker/login-action@v3 | ||
with: | ||
registry: ${{ env.REGISTRY }} | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Publish to GitHub Registry | ||
run: | | ||
last_git_sha=$(git log --pretty=format:'%h' HEAD -1) | ||
source_image_name=${{ steps.dockerImageName.outputs.dockerImageName }} | ||
echo "Using git tag $TAG_NAME" | ||
echo "Using last git sha $last_git_sha" | ||
echo "Context's github.sha = ${{ github.sha }}" | ||
echo "Images to tag => $source_image_name:$TAG_NAME" | ||
echo "Images to tag => $source_image_name:$last_git_sha" | ||
docker tag "$source_image_name" "$source_image_name:$TAG_NAME" | ||
docker tag "$source_image_name" "$source_image_name:$last_git_sha" | ||
docker push --all-tags ${{ steps.dockerImageName.outputs.dockerImageName }} |