diff --git a/.dockerignore b/.dockerignore index 20de602..8985017 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,75 @@ -# Ignore build artifacts +# Build artifacts and directories target/ +.quarkus/ +build/ +dist/ +out/ -# Ignore IDE and temporary files +# IDE files .idea/ *.iml .vscode/ +.eclipse/ +.metadata/ +.classpath +.project +.settings/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Git files +.git/ +.gitignore +.gitattributes + +# CI/CD files +.github/ +.gitlab-ci.yml + +# Documentation and markdown files +*.md +docs/ +doc/ + +# Log files +*.log +logs/ + +# Docker files (except Dockerfile) +docker-compose.yml +docker-compose.yaml +docker-compose.*.yml +docker-compose.*.yaml + +# License and legal files +LICENSE* +NOTICE* +COPYING* + +# Examples and samples +examples/ +samples/ + +# Kubernetes manifests (not needed for build) +deploy/ +k8s/ +kubernetes/ + +# Configuration files +.env +.env.local +.env.*.local +.editorconfig +.eslintrc.* +.prettierrc.* +.stylelintrc.* diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ab4572..e57a820 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,10 @@ on: branches: - main +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository_owner }}/podmortem-operator + jobs: test-build: name: Test Build on Pull Request @@ -16,6 +20,21 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Cache Maven dependencies + uses: actions/cache@v4 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -27,23 +46,42 @@ jobs: file: ./src/main/docker/Dockerfile.native platforms: linux/amd64 push: false - cache-from: type=gha + cache-from: | + type=gha + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache cache-to: type=gha,mode=max build-args: | GITHUB_USER=${{ github.actor }} GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} - build-and-push: - name: Build and Push on Main + build-platforms: + name: Build Multi-Platform Images if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: builder permissions: contents: read packages: write - + strategy: + matrix: + platform: [linux/amd64, linux/arm64] steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Cache Maven dependencies + uses: actions/cache@v4 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -51,23 +89,96 @@ jobs: - name: Log in to the GitHub Container Registry uses: docker/login-action@v3 with: - registry: ghcr.io + registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GH_PAT }} - - name: Build and push Docker image - id: build-and-push + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=sha,prefix={{branch}}- + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push by digest + id: build uses: docker/build-push-action@v6 with: context: . file: ./src/main/docker/Dockerfile.native - platforms: linux/amd64,linux/arm64 + platforms: ${{ matrix.platform }} push: true - cache-from: type=gha - cache-to: type=gha,mode=max - tags: | - ghcr.io/${{ github.repository_owner }}/podmortem-operator:latest - ghcr.io/${{ github.repository_owner }}/podmortem-operator:${{ github.sha }} + cache-from: | + type=gha + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache-${{ matrix.platform }} + cache-to: | + type=gha,mode=max + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache-${{ matrix.platform }},mode=max + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true build-args: | GITHUB_USER=${{ github.actor }} GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} + + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ matrix.platform }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge-manifests: + name: Create Multi-Platform Manifest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + needs: build-platforms + permissions: + contents: read + packages: write + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to the GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GH_PAT }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=sha,prefix={{branch}}- + type=raw,value=latest,enable={{is_default_branch}} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} diff --git a/src/main/docker/Dockerfile.native b/src/main/docker/Dockerfile.native index 5c0a807..af18975 100644 --- a/src/main/docker/Dockerfile.native +++ b/src/main/docker/Dockerfile.native @@ -1,24 +1,48 @@ FROM registry.access.redhat.com/quarkus/mandrel-for-jdk-21-rhel8:23.1 AS build WORKDIR /home/quarkus +ARG GITHUB_USER +ARG GITHUB_TOKEN +ENV GITHUB_USER=$GITHUB_USER +ENV GITHUB_TOKEN=$GITHUB_TOKEN + COPY --chown=quarkus:quarkus mvnw . COPY --chown=quarkus:quarkus .mvn .mvn COPY --chown=quarkus:quarkus pom.xml . -COPY --chown=quarkus:quarkus src src +COPY --chown=quarkus:quarkus src/main/resources/settings.xml src/main/resources/settings.xml USER quarkus -ARG GITHUB_USER -ARG GITHUB_TOKEN -ENV GITHUB_USER=$GITHUB_USER -ENV GITHUB_TOKEN=$GITHUB_TOKEN +RUN ./mvnw --no-transfer-progress -s src/main/resources/settings.xml \ + dependency:go-offline dependency:resolve-sources \ + -DexcludeGroupIds=com.redhat.podmortem + +COPY --chown=quarkus:quarkus src src -RUN ./mvnw --no-transfer-progress -s src/main/resources/settings.xml -U package -Dnative +RUN ./mvnw --no-transfer-progress -s src/main/resources/settings.xml \ + package -Dnative \ + -Dquarkus.native.additional-build-args="-J-Xmx8g,-J-XX:+UseG1GC,-J-XX:MaxGCPauseMillis=100,--initialize-at-build-time=org.slf4j.LoggerFactory,--initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder,--initialize-at-build-time=ch.qos.logback,--enable-preview,--strict-image-heap,-H:+ReportExceptionStackTraces,-H:+PrintGCApplicationConcurrentTime,-H:+PrintGCApplicationStoppedTime,-H:+PrintGC,-H:+VerboseGC" \ + -Dquarkus.native.enable-reports=true \ + -Dquarkus.native.enable-dashboard-dump=true FROM registry.access.redhat.com/ubi9/ubi-minimal +RUN microdnf update -y && \ + microdnf install -y shadow-utils && \ + groupadd -r appuser && useradd -r -g appuser appuser && \ + microdnf remove -y shadow-utils && \ + microdnf clean all + WORKDIR /work/ -COPY --from=build /home/quarkus/target/*-runner /work/application +COPY --from=build --chown=appuser:appuser /home/quarkus/target/*-runner /work/application + +RUN chmod 755 /work/application + +USER appuser EXPOSE 8080 -CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8080/q/health || exit 1 + +CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Dquarkus.http.port=8080"]