diff --git a/.github/workflows/gh-cli-docker-build-push.yml b/.github/workflows/gh-cli-docker-build-push.yml new file mode 100644 index 0000000..89f989b --- /dev/null +++ b/.github/workflows/gh-cli-docker-build-push.yml @@ -0,0 +1,156 @@ +name: Build github-workertools image + +on: + push: + branches: + - main + paths: + - github-cli/** + schedule: + - cron: '0 10 * * *' + workflow_dispatch: + +env: + REGISTRY_IMAGE_BASE: octopuslabs/workertools + REGISTRY_IMAGE: octopuslabs/github-workertools + +jobs: + + get-version-number: + runs-on: windows-latest + outputs: + CONTINUE: ${{ steps.check-version.outputs.CONTINUE }} + VERSION: ${{ steps.check-version.outputs.VERSION }} + steps: + - uses: actions/checkout@v4 + - id: check-version + name: Compare latest version with container + run: | + Write-Output "Getting github cli version" + $chocoInformationRaw = choco info gh --limitoutput + $versionOutput = ($chocoInformationRaw.Split("|"))[1] + + [System.Version]$version = $null + $versionParsed = [System.Version]::TryParse($versionOutput, [ref]$version) + if(-not $versionParsed) { + Write-Host "Unable to parse '$versionOutput' as a valid version. Won't continue" + echo "CONTINUE=No" >> $env:GITHUB_OUTPUT + } + else { + $versionToCompare = "$($version.Major).$($version.Minor).$($version.Build)" + Write-Host "Parsed version as $versionToCompare" + + $workerToolsTags = Invoke-RestMethod "https://registry.hub.docker.com/v2/repositories/${{ env.REGISTRY_IMAGE }}/tags?page_size=50" + $matchingTag = $workerToolsTags.results | Where-Object { $_.name -eq $versionToCompare } + + echo "VERSION=$versionToCompare" >> $env:GITHUB_OUTPUT + + if ($null -ne $matchingTag) + { + Write-Host "Docker container already has latest version" + echo "CONTINUE=No" >> $env:GITHUB_OUTPUT + } + else + { + Write-Host "We need to upgrade the container to $versionToCompare" + echo "CONTINUE=Yes" >> $env:GITHUB_OUTPUT + } + } + shell: pwsh + + build-linux: + needs: [get-version-number] + if: ${{ needs.get-version-number.outputs.CONTINUE == 'Yes' }} + strategy: + matrix: + os: + - ubuntu-latest + platform: + - linux/amd64 + - linux/arm64 + runs-on: ${{ matrix.os }} + steps: + + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + echo "PLATFORM_ARCH=${platform//[linux\/]/}" >> $GITHUB_ENV + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_PAT }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v5 + with: + context: github-cli/${{ env.PLATFORM_PAIR }} + platforms: ${{ matrix.platform }} + provenance: false + build-args: | + BASE_IMAGE=${{ env.REGISTRY_IMAGE_BASE }} + outputs: type=image,name=${{ env.REGISTRY_IMAGE }},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-${{ env.PLATFORM_PAIR }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + merge: + needs: [get-version-number, build-linux] + if: ${{ needs.get-version-number.outputs.CONTINUE == 'Yes' }} + runs-on: ubuntu-latest + env: + VERSION_NUMBER: ${{ needs.get-version-number.outputs.VERSION }} + 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: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: | + ${{ env.VERSION_NUMBER }} + latest + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_PAT }} + - 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_IMAGE }}@sha256:%s ' *) + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} \ No newline at end of file diff --git a/.github/workflows/gh-cli-ghcr-build-push.yml b/.github/workflows/gh-cli-ghcr-build-push.yml new file mode 100644 index 0000000..d6bff60 --- /dev/null +++ b/.github/workflows/gh-cli-ghcr-build-push.yml @@ -0,0 +1,162 @@ +name: Build GHCR github-workertools image + +permissions: + packages: write + +on: + push: + branches: + - main + paths: + - github-cli/** + schedule: + - cron: '0 10 * * *' + workflow_dispatch: + +env: + REGISTRY_IMAGE_BASE: ghcr.io/octopusdeploylabs/workertools + REGISTRY_IMAGE: ghcr.io/octopusdeploylabs/github-workertools + +jobs: + + get-version-number: + runs-on: windows-latest + outputs: + CONTINUE: ${{ steps.check-version.outputs.CONTINUE }} + VERSION: ${{ steps.check-version.outputs.VERSION }} + steps: + - uses: actions/checkout@v4 + - id: check-version + name: Compare latest version with container + run: | + Write-Output "Getting github cli version" + $chocoInformationRaw = choco info gh --limitoutput + $versionOutput = ($chocoInformationRaw.Split("|"))[1] + + [System.Version]$version = $null + $versionParsed = [System.Version]::TryParse($versionOutput, [ref]$version) + if(-not $versionParsed) { + Write-Host "Unable to parse '$versionOutput' as a valid version. Won't continue" + echo "CONTINUE=No" >> $env:GITHUB_OUTPUT + } + else { + $versionToCompare = "$($version.Major).$($version.Minor).$($version.Build)" + Write-Host "Parsed version as $versionToCompare" + + $token = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("${{ secrets.GITHUB_TOKEN }}")) + $workerToolsTags = Invoke-RestMethod -Uri "https://ghcr.io/v2/${{ env.REGISTRY_IMAGE }}/tags/list" -Headers @{Authorization="Bearer $token"} -SkipHttpErrorCheck + $matchingTag = $workerToolsTags.tags | Where-Object { $_ -eq $versionToCompare } + + echo "VERSION=$versionToCompare" >> $env:GITHUB_OUTPUT + + if ($null -ne $matchingTag -or ($null -ne $workerToolsTags.errors -and $workerToolsTags.errors[0].code -ne "NAME_UNKNOWN")) + { + Write-Host "Docker container already has latest version" + echo "CONTINUE=No" >> $env:GITHUB_OUTPUT + } + else + { + Write-Host "We need to upgrade the container to $versionToCompare" + echo "CONTINUE=Yes" >> $env:GITHUB_OUTPUT + } + } + shell: pwsh + + build-linux: + needs: [get-version-number] + if: ${{ needs.get-version-number.outputs.CONTINUE == 'Yes' }} + strategy: + matrix: + os: + - ubuntu-latest + platform: + - linux/amd64 + - linux/arm64 + runs-on: ${{ matrix.os }} + steps: + + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + echo "PLATFORM_ARCH=${platform//[linux\/]/}" >> $GITHUB_ENV + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: https://ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v5 + with: + context: github-cli/${{ env.PLATFORM_PAIR }} + platforms: ${{ matrix.platform }} + provenance: false + build-args: | + BASE_IMAGE=${{ env.REGISTRY_IMAGE_BASE }} + outputs: type=image,name=${{ env.REGISTRY_IMAGE }},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-${{ env.PLATFORM_PAIR }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + merge: + needs: [get-version-number, build-linux] + if: ${{ needs.get-version-number.outputs.CONTINUE == 'Yes' }} + runs-on: ubuntu-latest + env: + VERSION_NUMBER: ${{ needs.get-version-number.outputs.VERSION }} + 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: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: | + ${{ env.VERSION_NUMBER }} + latest + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: https://ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - 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_IMAGE }}@sha256:%s ' *) + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} \ No newline at end of file diff --git a/github-cli/linux-amd64/Dockerfile b/github-cli/linux-amd64/Dockerfile new file mode 100644 index 0000000..7a63bd3 --- /dev/null +++ b/github-cli/linux-amd64/Dockerfile @@ -0,0 +1,16 @@ +ARG BASE_IMAGE +FROM --platform=linux/amd64 ${BASE_IMAGE}:latest + +ARG DEBIAN_FRONTEND noninteractive + +# Install git +RUN apt-get update && apt-get install -y git + +# Install GitHub CLI +RUN mkdir -p -m 755 /etc/apt/keyrings \ + && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ + && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ + && apt update \ + && apt install gh -y + diff --git a/github-cli/linux-arm64/Dockerfile b/github-cli/linux-arm64/Dockerfile new file mode 100644 index 0000000..da873f4 --- /dev/null +++ b/github-cli/linux-arm64/Dockerfile @@ -0,0 +1,15 @@ +ARG BASE_IMAGE +FROM --platform=linux/arm64 ${BASE_IMAGE}:latest + +ARG DEBIAN_FRONTEND noninteractive + +# Install git +RUN apt-get update && apt-get install -y git + +# Install GitHub CLI +RUN mkdir -p -m 755 /etc/apt/keyrings \ + && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ + && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ + && apt update \ + && apt install gh -y