sync: Update blog posts from Obsidian (2026-01-26 14:39:57) #48
This file contains hidden or 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: CI on develop branch | |
| on: | |
| push: | |
| branches: | |
| - develop | |
| concurrency: | |
| group: build-minhdqdev-website-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| HARBOR_REGISTRY: harbor.minhdq.dev | |
| HARBOR_PROJECT: minhdqdev | |
| IMAGE_NAME: minhdqdev-website | |
| DOCKER_CLIENT_TIMEOUT: '240' | |
| COMPOSE_HTTP_TIMEOUT: '240' | |
| BUILD_NUMBER: ${{ github.run_number }} | |
| jobs: | |
| build-and-push: | |
| runs-on: [self-hosted, minhdqdev-org, manual] | |
| permissions: | |
| contents: read | |
| # Allow pushing to other repositories via GitHub token | |
| # Note: This requires ARGOCD_CONFIG_REPO_TOKEN secret with repo scope | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Extract version from package.json | |
| id: version | |
| run: | | |
| VERSION=$(jq -r '.version' package.json) | |
| if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then | |
| echo "ERROR: Could not extract version from package.json" >&2 | |
| exit 1 | |
| fi | |
| echo "VERSION=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Extracted version: $VERSION" | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Verify Harbor availability | |
| run: | | |
| set -euo pipefail | |
| ATTEMPTS=5 | |
| SUCCESS_CODES="200 301 302 401" | |
| for attempt in $(seq 1 $ATTEMPTS); do | |
| STATUS=$(curl -sS -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "https://${{ env.HARBOR_REGISTRY }}/v2/" || true) | |
| if printf '%s' "$SUCCESS_CODES" | grep -q "\b$STATUS\b"; then | |
| echo "Harbor responded with HTTP $STATUS on attempt $attempt/$ATTEMPTS" | |
| exit 0 | |
| fi | |
| echo "Harbor not reachable (HTTP ${STATUS:-N/A}) attempt $attempt/$ATTEMPTS" >&2 | |
| sleep $((attempt * 5)) | |
| done | |
| echo "Harbor is not reachable after $ATTEMPTS attempts" >&2 | |
| exit 1 | |
| - name: Log in to Harbor | |
| env: | |
| HARBOR_USERNAME: ${{ secrets.HARBOR_USERNAME }} | |
| HARBOR_PASSWORD: ${{ secrets.HARBOR_PASSWORD }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${HARBOR_USERNAME:-}" ] || [ -z "${HARBOR_PASSWORD:-}" ]; then | |
| echo "Harbor credentials are not configured" >&2 | |
| exit 1 | |
| fi | |
| ATTEMPTS=5 | |
| for attempt in $(seq 1 $ATTEMPTS); do | |
| if printf '%s' "$HARBOR_PASSWORD" | docker login "https://${{ env.HARBOR_REGISTRY }}" --username "$HARBOR_USERNAME" --password-stdin; then | |
| echo "Harbor login succeeded on attempt $attempt/$ATTEMPTS" | |
| exit 0 | |
| fi | |
| echo "Harbor login failed (attempt $attempt/$ATTEMPTS); waiting $((attempt * 5))s before retrying" >&2 | |
| sleep $((attempt * 5)) | |
| done | |
| echo "Unable to log in to Harbor after $ATTEMPTS attempts" >&2 | |
| exit 1 | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: | | |
| ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:develop | |
| ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:develop-${{ env.BUILD_NUMBER }} | |
| # Use inline cache: cache embedded in the develop tag itself | |
| cache-from: type=registry,ref=${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:develop | |
| cache-to: type=inline | |
| - name: Update ArgoCD kustomization | |
| env: | |
| GH_TOKEN: ${{ secrets.ARGOCD_CONFIG_REPO_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| # Clone ArgoCD config repo | |
| git clone https://x-access-token:${GH_TOKEN}@github.com/minhdqdev-org/minhdqdev-argocd-config.git /tmp/argocd-config | |
| cd /tmp/argocd-config | |
| # Configure git | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| # Update kustomization.yaml with new image tag | |
| KUSTOMIZATION_FILE="environments/uat/minhdqdev-website/kustomization.yaml" | |
| if [ ! -f "$KUSTOMIZATION_FILE" ]; then | |
| echo "ERROR: $KUSTOMIZATION_FILE not found" >&2 | |
| exit 1 | |
| fi | |
| # Update the image tag using yq or sed | |
| if command -v yq &> /dev/null; then | |
| yq eval ".images[0].newTag = \"develop-${{ env.BUILD_NUMBER }}\"" -i "$KUSTOMIZATION_FILE" | |
| else | |
| sed -i "s|newTag:.*|newTag: develop-${{ env.BUILD_NUMBER }}|" "$KUSTOMIZATION_FILE" | |
| fi | |
| # Commit and push if there are changes | |
| if git diff --quiet "$KUSTOMIZATION_FILE"; then | |
| echo "No changes to commit" | |
| else | |
| git add "$KUSTOMIZATION_FILE" | |
| git commit -m "chore: update minhdqdev-website UAT to develop-${{ env.BUILD_NUMBER }}" | |
| git push origin main | |
| echo "Updated $KUSTOMIZATION_FILE with tag develop-${{ env.BUILD_NUMBER }}" | |
| fi | |
| # Cleanup | |
| cd / | |
| rm -rf /tmp/argocd-config | |
| - name: Image build summary | |
| run: | | |
| echo "### Docker Image Built and Pushed :rocket:" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Registry:** ${{ env.HARBOR_REGISTRY }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Image:** ${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Version:** ${{ steps.version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Tags:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:develop\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:develop-${{ env.BUILD_NUMBER }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**ArgoCD:** Updated environments/uat/minhdqdev-website to develop-${{ env.BUILD_NUMBER }}" >> $GITHUB_STEP_SUMMARY |