From 1105037a3a270b89f09cf44fbaf996ccd38dd9fa Mon Sep 17 00:00:00 2001 From: bagas Date: Mon, 26 Jan 2026 17:32:29 +0700 Subject: [PATCH] ci: update build for multi-machine architecture support --- .gitea/workflows/build.yml | 295 +++++++++++++++++++++++++++---------- 1 file changed, 220 insertions(+), 75 deletions(-) diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 0f455d7..8871c8a 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -5,6 +5,7 @@ on: branches: - main - staging + - feat/testing tags: - 'v*' paths: @@ -15,12 +16,82 @@ on: - 'Dockerfile.*' - '.dockerignore' - '.gitea/workflows/build.yml' + - '.gitea/workflows/sonarqube.yml' jobs: - build-and-push-branches: + sonarqube: + name: SonarQube Scan runs-on: ubuntu-latest - if: github.ref_type == 'branch' + steps: + - name: Checking out + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: '1.25.5' + cache: false + + - name: Install dependencies + run: go mod tidy + + - name: Run go vet + run: go vet ./... 2>&1 | tee vet-results.txt + + - name: Run tests with coverage + run: | + go test ./... -v -coverprofile=coverage + + - name: Run GolangCI-Lint Analysis + uses: golangci/golangci-lint-action@v9 + with: + skip-cache: true + version: v2.6 + args: > + --issues-exit-code=0 + --output.text.path=stdout + --output.checkstyle.path=golangci-lint-report.xml + + - name: Set SonarQube project key + run: | + if [[ "$GITHUB_REF" == refs/tags/* ]]; then + TAG_NAME=${GITHUB_REF#refs/tags/} + BRANCH_KEY=${TAG_NAME//\//-} + SONAR_PROJECT_KEY="tunnel-please-$BRANCH_KEY" + elif [[ "$GITHUB_REF" == refs/heads/* ]]; then + BRANCH_NAME=${GITHUB_REF#refs/heads/} + if [ "$BRANCH_NAME" = "main" ]; then + SONAR_PROJECT_KEY="tunnel-please" + else + BRANCH_KEY=${BRANCH_NAME//\//-} + SONAR_PROJECT_KEY="tunnel-please-$BRANCH_KEY" + fi + else + SONAR_PROJECT_KEY="tunnel-please" + fi + echo "SONAR_PROJECT_KEY=$SONAR_PROJECT_KEY" >> $GITHUB_ENV + echo "Using SonarQube Project Key: $SONAR_PROJECT_KEY" + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@v7.0.0 + env: + SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST }} + SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} + with: + args: > + -Dsonar.projectKey=${{ env.SONAR_PROJECT_KEY }} + -Dsonar.go.coverage.reportPaths=coverage + -Dsonar.test.inclusions=**/*_test.go + -Dsonar.test.exclusions=**/vendor/** + -Dsonar.exclusions=**/*_test.go,**/vendor/**,**/golangci-lint-report.xml + -Dsonar.go.govet.reportPaths=vet-results.txt + -Dsonar.go.golangci-lint.reportPaths=golangci-lint-report.xml + + build-amd64: + runs-on: [ubuntu-latest, amd64] + needs: sonarqube steps: - name: Checkout repository uses: actions/checkout@v6 @@ -28,7 +99,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log in to Docker Hub + - name: Log in to Docker Registry uses: docker/login-action@v3 with: registry: git.fossy.my.id @@ -38,46 +109,48 @@ jobs: - name: Set version variables id: vars run: | - if [ "${{ github.ref }}" == "refs/heads/main" ]; then - echo "VERSION=dev-main" >> $GITHUB_OUTPUT + if [ "${{ github.ref_type }}" == "tag" ]; then + VERSION=${GITHUB_REF#refs/tags/v} + elif [ "${{ github.ref }}" == "refs/heads/main" ]; then + VERSION=dev-main else - echo "VERSION=dev-staging" >> $GITHUB_OUTPUT + BRANCH_NAME=${GITHUB_REF#refs/heads/} + VERSION=dev-${BRANCH_NAME//\//-} fi + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT echo "COMMIT=${{ github.sha }}" >> $GITHUB_OUTPUT - - name: Build and push Docker image for main + - name: Build and push AMD64 image + id: build uses: docker/build-push-action@v6 with: context: . push: true - tags: | - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:latest - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 build-args: | VERSION=${{ steps.vars.outputs.VERSION }} BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} COMMIT=${{ steps.vars.outputs.COMMIT }} - if: github.ref == 'refs/heads/main' + outputs: type=image,name=git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please,push-by-digest=true,name-canonical=true,push=true - - name: Build and push Docker image for staging - uses: docker/build-push-action@v6 + - 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@v3 with: - context: . - push: true - tags: | - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:staging - platforms: linux/amd64,linux/arm64 - build-args: | - VERSION=${{ steps.vars.outputs.VERSION }} - BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} - COMMIT=${{ steps.vars.outputs.COMMIT }} - if: github.ref == 'refs/heads/staging' - - build-and-push-tags: - runs-on: ubuntu-latest - if: github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v') + name: digests-amd64 + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + build-arm64: + runs-on: [ubuntu-latest, arm64] + needs: sonarqube steps: - name: Checkout repository uses: actions/checkout@v6 @@ -85,68 +158,140 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log in to Docker Hub + - name: Log in to Docker Registry uses: docker/login-action@v3 with: registry: git.fossy.my.id username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract version and determine release type - id: version + - name: Set version variables + id: vars run: | - VERSION=${GITHUB_REF#refs/tags/v} + if [ "${{ github.ref_type }}" == "tag" ]; then + VERSION=${GITHUB_REF#refs/tags/v} + elif [ "${{ github.ref }}" == "refs/heads/main" ]; then + VERSION=dev-main + else + BRANCH_NAME=${GITHUB_REF#refs/heads/} + VERSION=dev-${BRANCH_NAME//\//-} + fi echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT echo "COMMIT=${{ github.sha }}" >> $GITHUB_OUTPUT + + - name: Build and push ARM64 image + id: build + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/arm64 + build-args: | + VERSION=${{ steps.vars.outputs.VERSION }} + BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} + COMMIT=${{ steps.vars.outputs.COMMIT }} + outputs: type=image,name=git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please,push-by-digest=true,name-canonical=true,push=true + + - 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@v3 + with: + name: digests-arm64 + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + runs-on: ubuntu-latest + needs: + - sonarqube + - build-amd64 + - build-arm64 + if: | + always() && + needs.sonarqube.result == 'success' && + needs.build-amd64.result == 'success' && + needs.build-arm64.result == 'success' + + steps: + - name: Download digests + uses: actions/download-artifact@v3 + with: + path: /tmp/digests + + - name: Merge digests + run: | + mkdir -p /tmp/digests-merged + find /tmp/digests -type f -exec cp {} /tmp/digests-merged/ \; + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Registry + uses: docker/login-action@v3 + with: + registry: git.fossy.my.id + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Determine tags + id: tags + run: | + TAGS="" - if echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then - MAJOR=$(echo "$VERSION" | cut -d. -f1) - MINOR=$(echo "$VERSION" | cut -d. -f2) - - echo "MAJOR=$MAJOR" >> $GITHUB_OUTPUT - echo "MINOR=$MINOR" >> $GITHUB_OUTPUT - - if echo "$VERSION" | grep -q '-'; then - echo "IS_PRERELEASE=true" >> $GITHUB_OUTPUT - echo "ADDITIONAL_TAG=staging" >> $GITHUB_OUTPUT + if [ "${{ github.ref_type }}" == "tag" ]; then + VERSION=${GITHUB_REF#refs/tags/v} + + if echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then + MAJOR=$(echo "$VERSION" | cut -d. -f1) + MINOR=$(echo "$VERSION" | cut -d. -f2) + + TAGS="v${VERSION}" + + if echo "$VERSION" | grep -q '-'; then + TAGS="${TAGS},staging" + else + TAGS="${TAGS},v${MAJOR}.${MINOR},v${MAJOR},latest" + fi else - echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT - echo "ADDITIONAL_TAG=latest" >> $GITHUB_OUTPUT + echo "Invalid version format: $VERSION" + exit 1 fi + elif [ "${{ github.ref }}" == "refs/heads/main" ]; then + TAGS="latest" + elif [ "${{ github.ref }}" == "refs/heads/staging" ]; then + TAGS="staging" else - echo "Invalid version format: $VERSION" - exit 1 + BRANCH_NAME=${GITHUB_REF#refs/heads/} + BRANCH_TAG=${BRANCH_NAME//\//-} + TAGS="dev-${BRANCH_TAG}" fi + + echo "TAGS=$TAGS" >> $GITHUB_OUTPUT - - name: Build and push Docker image for release - uses: docker/build-push-action@v6 - with: - context: . - push: true - tags: | - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.VERSION }} - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.MAJOR }}.${{ steps.version.outputs.MINOR }} - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.MAJOR }} - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:${{ steps.version.outputs.ADDITIONAL_TAG }} - platforms: linux/amd64,linux/arm64 - build-args: | - VERSION=${{ steps.version.outputs.VERSION }} - BUILD_DATE=${{ steps.version.outputs.BUILD_DATE }} - COMMIT=${{ steps.version.outputs.COMMIT }} - if: steps.version.outputs.IS_PRERELEASE == 'false' + - name: Create manifest list and push + working-directory: /tmp/digests-merged + run: | + IFS=',' read -ra TAG_ARRAY <<< "${{ steps.tags.outputs.TAGS }}" + + CMD="docker buildx imagetools create" + + for tag in "${TAG_ARRAY[@]}"; do + CMD="$CMD -t git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:${tag}" + done + + CMD="$CMD $(printf 'git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please@sha256:%s ' *)" + + eval $CMD - - name: Build and push Docker image for pre-release - uses: docker/build-push-action@v6 - with: - context: . - push: true - tags: | - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:v${{ steps.version.outputs.VERSION }} - git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:${{ steps.version.outputs.ADDITIONAL_TAG }} - platforms: linux/amd64,linux/arm64 - build-args: | - VERSION=${{ steps.version.outputs.VERSION }} - BUILD_DATE=${{ steps.version.outputs.BUILD_DATE }} - COMMIT=${{ steps.version.outputs.COMMIT }} - if: steps.version.outputs.IS_PRERELEASE == 'true' + - name: Inspect image + run: | + IFS=',' read -ra TAG_ARRAY <<< "${{ steps.tags.outputs.TAGS }}" + FIRST_TAG="${TAG_ARRAY[0]}" + docker buildx imagetools inspect git.fossy.my.id/${{ secrets.DOCKER_USERNAME }}/tunnel-please:${FIRST_TAG} \ No newline at end of file