Skip to content

Release: Update Repositories [v8] #25

Release: Update Repositories [v8]

Release: Update Repositories [v8] #25

name: "Release: Update Repositories"
run-name: "Release: Update Repositories [${{ github.ref_name }}]"
on:
workflow_dispatch:
inputs:
build_version:
description: 'build version format: n.n.n'
required: true
type: string
permissions:
contents: write
defaults:
run:
shell: bash
jobs:
setup:
name: Setup
runs-on: ubuntu-latest
if: ${{ github.action_repository != 'cloudfoundry/cli' }}
outputs:
version-build: ${{ steps.parse-semver.outputs.version-build }}
version-major: ${{ steps.parse-semver.outputs.version-major }}
version-minor: ${{ steps.parse-semver.outputs.version-minor }}
version-patch: ${{ steps.parse-semver.outputs.version-patch }}
claw-url: ${{ steps.set-claw-url.outputs.claw-url }}
steps:
- name: Set CLAW URL
id: set-claw-url
run: echo "claw-url=https://packages.cloudfoundry.org" >> "${GITHUB_OUTPUT}"
- name: Checkout cli
uses: actions/checkout@v4
- name: Parse semver
id: parse-semver
run: |
VERSION=$(cat BUILD_VERSION)
VERSION="${VERSION#[vV]}"
VERSION_MINOR="${VERSION#*.}"
VERSION_MINOR="${VERSION_MINOR%.*}"
echo "version-build=${VERSION}" >> "${GITHUB_OUTPUT}"
echo "version-major=${VERSION%%\.*}" >> "${GITHUB_OUTPUT}"
echo "version-minor=${VERSION_MINOR}" >> "${GITHUB_OUTPUT}"
echo "version-patch=${VERSION##*.}" >> "${GITHUB_OUTPUT}"
echo "VERSION_BUILD=${VERSION}" >> "${GITHUB_ENV}"
- name: Test if CLAW serve this version
env:
CLAW_URL: ${{ steps.set-claw-url.outputs.claw-url }}
run: >
set -vx
curl --head "${CLAW_URL}/stable?release=linux64-binary&version=${VERSION_BUILD}&source=test" 2>&1 |
grep --quiet --regexp 'HTTP.*302'
update-homebrew:
name: Update Homebrew Repository
runs-on: ubuntu-latest
needs: setup
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Checkout cli-ci
uses: actions/checkout@v4
with:
repository: cloudfoundry/cli-ci.git
ref: main
path: cli-ci
- name: Checkout homebrew-tap
uses: actions/checkout@v4
with:
repository: cloudfoundry/homebrew-tap
ref: master
path: homebrew-tap
ssh-key: ${{ secrets.GIT_DEPLOY_HOMEBREW_TAP }}
- name: Setup
run: >
mkdir
cf-cli-osx-tarball
cf-cli-macosarm-tarball
cf-cli-linux-tarball
- name: Calculate checksums
run: |
set -x
curl -L "${CLAW_URL}/stable?release=macosx64-binary&version=${VERSION_BUILD}&source=github-rel" \
> cf-cli-osx-tarball/cf-cli_osx.tgz
curl -L "${CLAW_URL}/stable?release=macosarm-binary&version=${VERSION_BUILD}&source=github-rel" \
> cf-cli-macosarm-tarball/cf-cli_macosarm.tgz
curl -L "${CLAW_URL}/stable?release=linux64-binary&version=${VERSION_BUILD}&source=github-rel" \
> cf-cli-linux-tarball/cf-cli_linux64.tgz
curl -L "${CLAW_URL}/stable?release=linuxarm64-binary&version=${VERSION_BUILD}&source=github-rel" \
> cf-cli-linux-tarball/cf-cli_linuxarm64.tgz
# Because CLAW always returns 200 we have to check if we got archive
file cf-cli-osx-tarball/cf-cli_osx.tgz | grep -q gzip || exit 1
file cf-cli-macosarm-tarball/cf-cli_macosarm.tgz | grep -q gzip || exit 1
file cf-cli-linux-tarball/cf-cli_linux64.tgz | grep -q gzip || exit 1
file cf-cli-linux-tarball/cf-cli_linuxarm64.tgz | grep -q gzip || exit 1
pushd cf-cli-osx-tarball
CLI_OSX_SHA256=$(shasum -a 256 cf-cli_osx.tgz | cut -d ' ' -f 1)
popd
pushd cf-cli-macosarm-tarball
CLI_MACOSARM_SHA256=$(shasum -a 256 cf-cli_macosarm.tgz | cut -d ' ' -f 1)
popd
pushd cf-cli-linux-tarball
CLI_LINUX_64_SHA256=$(shasum -a 256 cf-cli_linux64.tgz | cut -d ' ' -f 1)
popd
pushd cf-cli-linux-tarball
CLI_LINUX_ARM64_SHA256=$(shasum -a 256 cf-cli_linuxarm64.tgz | cut -d ' ' -f 1)
popd
echo "CLI_OSX_SHA256=${CLI_OSX_SHA256}" >> "${GITHUB_ENV}"
echo "CLI_MACOSARM_SHA256=${CLI_MACOSARM_SHA256}" >> "${GITHUB_ENV}"
echo "CLI_LINUX_64_SHA256=${CLI_LINUX_64_SHA256}" >> "${GITHUB_ENV}"
echo "CLI_LINUX_ARM64_SHA256=${CLI_LINUX_ARM64_SHA256}" >> "${GITHUB_ENV}"
- name: Generate Homebrew formula file
run: |
set -ex
pushd homebrew-tap
cat <<EOF > cf-cli@${VERSION_MAJOR}.rb
class CfCliAT${VERSION_MAJOR} < Formula
desc "Cloud Foundry CLI"
homepage "https://code.cloudfoundry.org/cli"
version "${VERSION_BUILD}"
if OS.mac?
if Hardware::CPU.arm?
url "${CLAW_URL}/homebrew?arch=macosarm&version=${VERSION_BUILD}"
sha256 "${CLI_MACOSARM_SHA256}"
elsif
url "${CLAW_URL}/homebrew?arch=macosx64&version=${VERSION_BUILD}"
sha256 "${CLI_OSX_SHA256}"
end
elsif OS.linux?
url "${CLAW_URL}/stable?release=linux64-binary&version=${VERSION_BUILD}&source=homebrew"
sha256 "${CLI_LINUX_64_SHA256}"
end
def install
bin.install "cf${VERSION_MAJOR}"
bin.install_symlink "cf${VERSION_MAJOR}" => "cf"
(bash_completion/"cf${VERSION_MAJOR}-cli").write <<-completion
$(cat ../cli-ci/ci/installers/completion/cf${VERSION_MAJOR})
completion
doc.install "LICENSE"
doc.install "NOTICE"
end
test do
system "#{bin}/cf${VERSION_MAJOR}"
end
end
EOF
popd
- name: Commit new homebrew formula
run: |
pushd homebrew-tap
git add cf-cli@${VERSION_MAJOR}.rb
if ! [ -z "$(git status --porcelain)"]; then
git config user.name github-actions
git config user.email [email protected]
git commit -m "Release CF CLI ${VERSION_BUILD}"
else
echo "no new version to commit"
fi
git push
echo "::group::cf-cli@${VERSION_MAJOR}.rb"
cat cf-cli@${VERSION_MAJOR}.rb
echo "::endgroup::"
echo "::group::git show"
git show
echo "::endgroup::"
popd
test-homebrew:
name: Test Homebrew Repository
runs-on: macos-latest
needs:
- setup
- update-homebrew
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Install CF CLI via Homebrew
run: |
set -evx
brew install cloudfoundry/tap/cf-cli@${VERSION_MAJOR}
installed_cf_version=$(cf${VERSION_MAJOR} version)
cf_location=$(which cf)
echo $cf_location
echo $installed_cf_version
echo ${VERSION_BUILD}
codesign --verify $cf_location || echo ---
cf -v | grep "${VERSION_BUILD}"
update-deb:
name: Update Debian Repository
runs-on: ubuntu-20.04
needs: setup
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Setup
run: |
echo "VERSION_BUILD: ${VERSION_BUILD}"
echo "Environment: ${ENVIRONMENT}"
- name: Checkout
uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- run: gem install deb-s3
#RUN apt install -y ruby1.9.1 createrepo
- name: Load GPG key
env:
SIGNING_KEY_GPG: ${{ secrets.SIGNING_KEY_GPG }}
SIGNING_KEY_GPG_PASSPHRASE: ${{ secrets.SIGNING_KEY_GPG_PASSPHRASE }}
run: |
echo -n "${SIGNING_KEY_GPG}" | base64 --decode | gpg --no-tty --batch --pinentry-mode loopback --import
- name: View GPG keys
run: gpg --list-keys
- name: Configure GPG
run: |
echo "Configure GPG"
# mkdir gpg-dir
# export GNUPGHOME=${PWD}/gpg-dir
# chmod 700 ${GNUPGHOME}
# TODO: restore
# trap "rm -rf ${GNUPGHOME}" 0
cat >> ~/gpg.conf <<EOF
personal-digest-preferences SHA256
cert-digest-algo SHA256
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
EOF
- name: Download New Debian Packages From CLAW
run: |
mkdir installers
curl -L "${CLAW_URL}/stable?release=debian32&version=${VERSION_BUILD}&source=github-rel" > installers/cf${VERSION_MAJOR}-cli-installer_${VERSION_BUILD}_i686.deb
curl -L "${CLAW_URL}/stable?release=debian64&version=${VERSION_BUILD}&source=github-rel" > installers/cf${VERSION_MAJOR}-cli-installer_${VERSION_BUILD}_x86-64.deb
curl -L "${CLAW_URL}/stable?release=debianarm64&version=${VERSION_BUILD}&source=github-rel" > installers/cf${VERSION_MAJOR}-cli-installer_${VERSION_BUILD}_arm64.deb
- name: Update Debian Repository
env:
DEBIAN_FRONTEND: noninteractive
SIGNING_KEY_GPG_ID: ${{ vars.SIGNING_KEY_GPG_ID }}
AWS_ACCESS_KEY_ID: ${{ vars.AWS_ACCESS_KEY_ID }}
AWS_BUCKET_NAME: cf-cli-debian-repo
AWS_DEFAULT_REGION: us-west-2
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_S3_ROLE_ARN: ${{ vars.AWS_S3_ROLE_ARN }}
run: |
export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role --role-arn ${AWS_S3_ROLE_ARN} --role-session-name foobar --output text --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]"))
deb-s3 upload installers/*.deb \
--preserve-versions \
--bucket=${AWS_BUCKET_NAME} \
--sign=${SIGNING_KEY_GPG_ID}
test-deb:
name: Test Debian Repository
runs-on: ubuntu-20.04
needs:
- setup
- update-deb
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Install CF CLI via apt
run: |
set -o pipefail -e
sudo apt update
sudo apt install -y wget gnupg
wget -q -O - ${CLAW_URL}/debian/cli.cloudfoundry.org.key | sudo apt-key add -
echo "deb ${CLAW_URL}/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list
sudo apt update
sudo apt install -y cf${VERSION_MAJOR}-cli
which cf
set -x
cf -v
cf${VERSION_MAJOR} -v
cf -v | grep "${VERSION_BUILD}"
update-rpm:
name: Update RPM Repository
runs-on: ubuntu-latest
needs: setup
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Setup
env:
ENVIRONMENT: ${{ github.event.inputs.environment }}
VERSION_BUILD: ${{ github.event.inputs.build_version }}
run: |
echo "VERSION_BUILD: ${VERSION_BUILD}"
echo "Environment: ${ENVIRONMENT}"
# TODO: fix backup
# - name: Download current RPM repodata
# env:
# AWS_ACCESS_KEY_ID: ${{ vars.AWS_ACCESS_KEY_ID }}
# AWS_DEFAULT_REGION: us-east-1
# AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# uses: docker://amazon/aws-cli:latest
# with:
# args: >
# s3 cp --recursive
# s3://cf-cli-rpm-repo/
# backup
# TODO: fix https://aws.amazon.com/premiumsupport/knowledge-center/s3-access-denied-listobjects-sync/
#
# - name: List assets
# run: |
# ls -R
#
# - name: Backup current Linux RPM repodata
# uses: actions/upload-artifact@v4
# with:
# if-no-files-found: error
# name: cf-cli-linux-rpm-repodata-backup
# path: backup
- name: Install Linux Packages
env:
DEBIAN_FRONTEND: noninteractive
run: >
sudo apt update &&
sudo apt install --yes --no-install-recommends
gnupg
createrepo-c
awscli
- name: Setup aws to upload installers to CLAW S3 bucket
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ vars.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: ${{ vars.AWS_S3_ROLE_ARN }}
role-skip-session-tagging: true
role-duration-seconds: 1200
- name: Download V8 RPMs
run: aws s3 sync --exclude "*" --include "releases/*/*installer*.rpm" s3://v8-cf-cli-releases .
- name: Download V7 RPMs
run: aws s3 sync --exclude "*" --include "releases/*/*installer*.rpm" s3://v7-cf-cli-releases .
- name: Download V6 RPMs
run: aws s3 sync --exclude "*" --include "releases/*/*installer*.rpm" s3://cf-cli-releases .
- name: Sign repo
run: createrepo_c --checksum=sha .
- name: List assets
run: ls -R
- name: Store Linux RPM repodata
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: cf-cli-linux-rpm-repodata
path: repodata
- name: Upload RPM repodata
run: aws s3 sync --delete repodata s3://cf-cli-rpm-repo/repodata
test-rpm-repo:
name: Test RPM Repository
needs:
- setup
- update-rpm
runs-on: ubuntu-latest
container:
image: fedora
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Configure Custom CF Repository
run: |
curl -sL -o /etc/yum.repos.d/cloudfoundry-cli.repo \
${CLAW_URL}/fedora/cloudfoundry-cli.repo
- name: Install cf cli package
run: dnf install -y cf${VERSION_MAJOR}-cli
- name: Print CF CLI Versions
run: |
cf -v
cf${VERSION_MAJOR} -v
- name: Test Version Match
run: cf -v | grep -q "${VERSION_BUILD}"
update-windows:
name: Update Windows Chocolatey Package
runs-on: windows-2019
defaults:
run:
shell: pwsh
needs: setup
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Setup
run: |
echo "VERSION_BUILD: ${VERSION_BUILD}"
echo "Environment: ${ENVIRONMENT}"
- name: Checkout
uses: actions/checkout@v4
- name: Calculate Checksums
run: |
foreach ($bit in @('32', '64')) {
$file="cf-cli_win${bit}.zip"
Invoke-WebRequest "${env:CLAW_URL}/stable?release=windows${bit}-exe&version=${env:VERSION_BUILD}&source=github-rel" `
-OutFile $file
if (-not (Test-Path -Path $file)) {
Write-Error "Failed to download $file" -ErrorAction Stop
}
$hash = (Get-FileHash $file).Hash
Add-Content -Path "$env:GITHUB_ENV" -Value "CLI_WIN${bit}_SHA256=$hash"
}
- name: Render Chocolatey Templates
run: |
# Ensure current directory is accurate for WriteAllLines
[System.Environment]::CurrentDirectory = (Get-Location).Path
# Use WriteAllLines because it uses UTF8 without a BOM
$nuspec = (Get-Content -Encoding utf8 -Raw ./.github/win/choco/cloudfoundry-cli.nuspec.tmpl).
Replace('${version}', $env:VERSION_BUILD)
[System.IO.File]::WriteAllLines('./cloudfoundry-cli.nuspec', $nuspec)
Get-Content ./cloudfoundry-cli.nuspec
New-Item -Path ./tools -ItemType Directory -Force | Out-Null
(Get-Content -Encoding utf8 -Raw ./.github/win/choco/chocolateyinstall.ps1.tmpl).
Replace('${version}', $env:VERSION_BUILD). `
Replace('${checksum}', $env:CLI_WIN32_SHA256). `
Replace('${checksum64}', $env:CLI_WIN64_SHA256). `
Replace('${claw_url}', $env:CLAW_URL) | `
Set-Content ./tools/chocolateyinstall.ps1 -Encoding utf8
Get-Content ./tools/chocolateyinstall.ps1
- name: Create Chocolatey Package
run: |
choco pack ./cloudfoundry-cli.nuspec
- name: Push Chocolatey Package
env:
CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }}
run: |
choco config set --name=defaultPushSource --value=https://push.chocolatey.org/
choco setapikey --key $env:CHOCO_API_KEY --source https://push.chocolatey.org/
choco push "cloudfoundry-cli.$env:VERSION_BUILD.nupkg"
test-windows:
name: Test Windows Chocolatey Package
runs-on: windows-2019
defaults:
run:
shell: pwsh
needs:
- setup
- update-windows
env:
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Install cf cli package
run: choco install cloudfoundry-cli --version $env:VERSION_BUILD
- name: Print Chocolatey CF CLI Versions
run: |
cd 'C:/ProgramData/chocolatey/lib/cloudfoundry-cli/tools'
./cf -v
Invoke-Expression "./cf$env:VERSION_MAJOR -v"
- name: Test Chocolatey Version Match
run: |
cd 'C:/ProgramData/chocolatey/lib/cloudfoundry-cli/tools'
$found = (./cf -v | Select-String "$env:VERSION_BUILD")
if ($null -eq $found) {
Write-Error "CF CLI version $env:VERSION_BUILD was not found" -ErrorAction Stop
}
build-docker:
name: Build Docker Image
runs-on: ubuntu-latest
needs: setup
env:
CLAW_URL: ${{ needs.setup.outputs.claw-url }}
VERSION_BUILD: ${{ needs.setup.outputs.version-build }}
VERSION_MAJOR: ${{ needs.setup.outputs.version-major }}
steps:
- name: Setup
env:
ENVIRONMENT: ${{ github.event.inputs.environment }}
VERSION_BUILD: ${{ github.event.inputs.build_version }}
run: |
echo "VERSION_BUILD: ${VERSION_BUILD}"
echo "Environment: ${ENVIRONMENT}"
- name: Checkout
uses: actions/checkout@v4
with:
repository: cloudfoundry/cli
ref: ${{ github.ref_name }}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and export to Docker locally
uses: docker/build-push-action@v6
with:
context: docker
load: true
tags: ${{ env.VERSION_BUILD }}
- name: Test docker container
run: |
cat <<\EOF > test.sh
set -eux
# Test if CLI inside container is correct
if ! [ -x "$(command -v cf)" ]; then
echo 'Error: cf is not installed.' >&2
exit 1
fi
CF_VERSION="$(cf -v)"
VERSION=${{ env.VERSION_BUILD }}
if [[ ! "${CF_VERSION}" == *"cf version $VERSION"* ]]; then
echo "Error: cf -v did not match expected version"
echo "Expected: $VERSION"
echo "Got ${CF_VERSION}"
exit 1
fi
EOF
chmod 700 test.sh
docker run -v $(pwd):/clidir -w /clidir \
--rm ${{ env.VERSION_BUILD }} sh test.sh
# If bash reaches this point, it means that tests passed, setting latest
if [[ ( ${{ github.ref_name }} == "v8" ) ]]; then
echo "LATEST_DOCKER=v8" >> "$GITHUB_ENV"
fi
if [[ ( ${{ github.ref_name }} == "v7" ) ]]; then
echo "LATEST_DOCKER=v7" >> "$GITHUB_ENV"
fi
rm test.sh
- name: Push image if its from v8
if: ${{ env.LATEST_DOCKER }} == v8
uses: docker/build-push-action@v6
with:
context: docker
push: true
tags: cloudfoundry/cli:${{ env.VERSION_BUILD }}, cloudfoundry/cli:latest
- name: Push image if its from v7
if: ${{ env.LATEST_DOCKER }} == v7
uses: docker/build-push-action@v6
with:
context: docker
push: true
tags: cloudfoundry/cli:${{ env.VERSION_BUILD }}
# vim: set sw=2 ts=2 sts=2 et tw=78 foldlevel=2 fdm=indent nospell: