diff --git a/.github/workflows/workspace-release.yaml b/.github/workflows/workspace-release.yaml new file mode 100644 index 0000000..8e29f82 --- /dev/null +++ b/.github/workflows/workspace-release.yaml @@ -0,0 +1,182 @@ +name: Build & Push Workspace Docker Image on Release + +on: + release: + types: [published] + +jobs: + prepare-metadata: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.meta.outputs.version }} + is_prerelease: ${{ steps.meta.outputs.is_prerelease }} + prerelease_type: ${{ steps.meta.outputs.prerelease_type }} + tags_suffix: ${{ steps.tags.outputs.tags_suffix }} + steps: + - name: Extract release metadata + id: meta + run: | + VERSION="${GITHUB_REF_NAME}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + + if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then + echo "is_prerelease=true" >> $GITHUB_OUTPUT + + if [[ "$VERSION" =~ -([a-zA-Z]+)\. ]]; then + PRERELEASE_TYPE="${BASH_REMATCH[1]}" + echo "prerelease_type=$PRERELEASE_TYPE" >> $GITHUB_OUTPUT + else + echo "prerelease_type=beta" >> $GITHUB_OUTPUT + fi + else + echo "is_prerelease=false" >> $GITHUB_OUTPUT + fi + + - name: Determine Docker tags + id: tags + run: | + TAGS_SUFFIX="${{ steps.meta.outputs.version }}" + + if [[ "${{ steps.meta.outputs.is_prerelease }}" == "true" ]]; then + TAGS_SUFFIX="$TAGS_SUFFIX,${{ steps.meta.outputs.prerelease_type }}" + else + TAGS_SUFFIX="$TAGS_SUFFIX,latest" + + VERSION="${{ steps.meta.outputs.version }}" + if [[ "$VERSION" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + MAJOR="${BASH_REMATCH[1]}" + MINOR="${BASH_REMATCH[2]}" + TAGS_SUFFIX="$TAGS_SUFFIX,$MAJOR" + TAGS_SUFFIX="$TAGS_SUFFIX,$MAJOR.$MINOR" + fi + fi + + echo "tags_suffix=$TAGS_SUFFIX" >> $GITHUB_OUTPUT + + build-amd64: + runs-on: builder-amd64-16-core + needs: prepare-metadata + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + with: + buildkitd-flags: --debug + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push AMD64 image + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: sysops/dockerfiles/agent.Dockerfile + platforms: linux/amd64 + outputs: type=image,name=lifecycleoss/workspace,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@v4 + with: + name: digests-amd64 + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + build-arm64: + runs-on: builder-arm64-16-core + needs: prepare-metadata + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + with: + buildkitd-flags: --debug + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push ARM64 image + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: sysops/dockerfiles/agent.Dockerfile + platforms: linux/arm64 + outputs: type=image,name=lifecycleoss/workspace,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@v4 + with: + name: digests-arm64 + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge-and-push: + runs-on: builder-amd64-16-core + needs: + - prepare-metadata + - build-amd64 + - build-arm64 + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-* + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Create manifest list and push + env: + TAGS_SUFFIX: ${{ needs.prepare-metadata.outputs.tags_suffix }} + run: | + AMD64_DIGEST=$(find /tmp/digests/digests-amd64 -type f | head -1) + ARM64_DIGEST=$(find /tmp/digests/digests-arm64 -type f | head -1) + + AMD64_SHA=$(basename "$AMD64_DIGEST") + ARM64_SHA=$(basename "$ARM64_DIGEST") + + DIGESTS="lifecycleoss/workspace@sha256:$AMD64_SHA lifecycleoss/workspace@sha256:$ARM64_SHA" + + IFS=',' read -ra TAG_ARRAY <<< "$TAGS_SUFFIX" + + for TAG_SUFFIX in "${TAG_ARRAY[@]}"; do + TAG_SUFFIX=$(echo "$TAG_SUFFIX" | xargs) + FULL_TAG="lifecycleoss/workspace:${TAG_SUFFIX}" + docker buildx imagetools create -t "$FULL_TAG" $DIGESTS + done + + - name: Inspect final image + run: | + docker buildx imagetools inspect lifecycleoss/workspace:${{ needs.prepare-metadata.outputs.version }}