mirror of
https://github.com/fumiama/terasu-cloudflared.git
synced 2026-06-09 04:30:31 +08:00
TUN-9803: Add windows builds to gitlab-ci
This commit is contained in:
228
.ci/scripts/mac/build.sh
Executable file
228
.ci/scripts/mac/build.sh
Executable file
@@ -0,0 +1,228 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -exo pipefail
|
||||
|
||||
if [[ "$(uname)" != "Darwin" ]] ; then
|
||||
echo "This should be run on macOS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "amd64" != "${TARGET_ARCH}" && "arm64" != "${TARGET_ARCH}" ]]
|
||||
then
|
||||
echo "TARGET_ARCH must be amd64 or arm64"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
go version
|
||||
export GO111MODULE=on
|
||||
|
||||
# build 'cloudflared-darwin-amd64.tgz'
|
||||
mkdir -p artifacts
|
||||
TARGET_DIRECTORY=".build"
|
||||
BINARY_NAME="cloudflared"
|
||||
VERSION=$(git describe --tags --always --dirty="-dev")
|
||||
PRODUCT="cloudflared"
|
||||
APPLE_CA_CERT="apple_dev_ca.cert"
|
||||
CODE_SIGN_PRIV="code_sign.p12"
|
||||
CODE_SIGN_CERT="code_sign.cer"
|
||||
INSTALLER_PRIV="installer.p12"
|
||||
INSTALLER_CERT="installer.cer"
|
||||
BUNDLE_ID="com.cloudflare.cloudflared"
|
||||
SEC_DUP_MSG="security: SecKeychainItemImport: The specified item already exists in the keychain."
|
||||
export PATH="$PATH:/usr/local/bin"
|
||||
FILENAME="$(pwd)/artifacts/cloudflared-darwin-$TARGET_ARCH.tgz"
|
||||
PKGNAME="$(pwd)/artifacts/cloudflared-$TARGET_ARCH.pkg"
|
||||
mkdir -p ../src/github.com/cloudflare/
|
||||
cp -r . ../src/github.com/cloudflare/cloudflared
|
||||
cd ../src/github.com/cloudflare/cloudflared
|
||||
|
||||
# Imports certificates to the Apple KeyChain
|
||||
import_certificate() {
|
||||
local CERTIFICATE_NAME=$1
|
||||
local CERTIFICATE_ENV_VAR=$2
|
||||
local CERTIFICATE_FILE_NAME=$3
|
||||
|
||||
echo "Importing $CERTIFICATE_NAME"
|
||||
|
||||
if [[ ! -z "$CERTIFICATE_ENV_VAR" ]]; then
|
||||
# write certificate to disk and then import it keychain
|
||||
echo -n -e ${CERTIFICATE_ENV_VAR} | base64 -D > ${CERTIFICATE_FILE_NAME}
|
||||
# we set || true here and for every `security import invoke` because the "duplicate SecKeychainItemImport" error
|
||||
# will cause set -e to exit 1. It is okay we do this because we deliberately handle this error in the lines below.
|
||||
local out=$(security import ${CERTIFICATE_FILE_NAME} -T /usr/bin/pkgbuild -A 2>&1) || true
|
||||
local exitcode=$?
|
||||
# delete the certificate from disk
|
||||
rm -rf ${CERTIFICATE_FILE_NAME}
|
||||
if [ -n "$out" ]; then
|
||||
if [ $exitcode -eq 0 ]; then
|
||||
echo "$out"
|
||||
else
|
||||
if [ "$out" != "${SEC_DUP_MSG}" ]; then
|
||||
echo "$out" >&2
|
||||
exit $exitcode
|
||||
else
|
||||
echo "already imported code signing certificate"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
create_cloudflared_build_keychain() {
|
||||
# Reusing the private key password as the keychain key
|
||||
local PRIVATE_KEY_PASS=$1
|
||||
|
||||
# Create keychain only if it doesn't already exist
|
||||
if [ ! -f "$HOME/Library/Keychains/cloudflared_build_keychain.keychain-db" ]; then
|
||||
security create-keychain -p "$PRIVATE_KEY_PASS" cloudflared_build_keychain
|
||||
else
|
||||
echo "Keychain already exists: cloudflared_build_keychain"
|
||||
fi
|
||||
|
||||
# Append temp keychain to the user domain
|
||||
security list-keychains -d user -s cloudflared_build_keychain $(security list-keychains -d user | sed s/\"//g)
|
||||
|
||||
# Remove relock timeout
|
||||
security set-keychain-settings cloudflared_build_keychain
|
||||
|
||||
# Unlock keychain so it doesn't require password
|
||||
security unlock-keychain -p "$PRIVATE_KEY_PASS" cloudflared_build_keychain
|
||||
|
||||
}
|
||||
|
||||
# Imports private keys to the Apple KeyChain
|
||||
import_private_keys() {
|
||||
local PRIVATE_KEY_NAME=$1
|
||||
local PRIVATE_KEY_ENV_VAR=$2
|
||||
local PRIVATE_KEY_FILE_NAME=$3
|
||||
local PRIVATE_KEY_PASS=$4
|
||||
|
||||
echo "Importing $PRIVATE_KEY_NAME"
|
||||
|
||||
if [[ ! -z "$PRIVATE_KEY_ENV_VAR" ]]; then
|
||||
if [[ ! -z "$PRIVATE_KEY_PASS" ]]; then
|
||||
# write private key to disk and then import it keychain
|
||||
echo -n -e ${PRIVATE_KEY_ENV_VAR} | base64 -D > ${PRIVATE_KEY_FILE_NAME}
|
||||
# we set || true here and for every `security import invoke` because the "duplicate SecKeychainItemImport" error
|
||||
# will cause set -e to exit 1. It is okay we do this because we deliberately handle this error in the lines below.
|
||||
local out=$(security import ${PRIVATE_KEY_FILE_NAME} -k cloudflared_build_keychain -P "$PRIVATE_KEY_PASS" -T /usr/bin/pkgbuild -A -P "${PRIVATE_KEY_PASS}" 2>&1) || true
|
||||
local exitcode=$?
|
||||
rm -rf ${PRIVATE_KEY_FILE_NAME}
|
||||
if [ -n "$out" ]; then
|
||||
if [ $exitcode -eq 0 ]; then
|
||||
echo "$out"
|
||||
else
|
||||
if [ "$out" != "${SEC_DUP_MSG}" ]; then
|
||||
echo "$out" >&2
|
||||
exit $exitcode
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Create temp keychain only for this build
|
||||
create_cloudflared_build_keychain "${CFD_CODE_SIGN_PASS}"
|
||||
|
||||
# Add Apple Root Developer certificate to the key chain
|
||||
import_certificate "Apple Developer CA" "${APPLE_DEV_CA_CERT}" "${APPLE_CA_CERT}"
|
||||
|
||||
# Add code signing private key to the key chain
|
||||
import_private_keys "Developer ID Application" "${CFD_CODE_SIGN_KEY}" "${CODE_SIGN_PRIV}" "${CFD_CODE_SIGN_PASS}"
|
||||
|
||||
# Add code signing certificate to the key chain
|
||||
import_certificate "Developer ID Application" "${CFD_CODE_SIGN_CERT}" "${CODE_SIGN_CERT}"
|
||||
|
||||
# Add package signing private key to the key chain
|
||||
import_private_keys "Developer ID Installer" "${CFD_INSTALLER_KEY}" "${INSTALLER_PRIV}" "${CFD_INSTALLER_PASS}"
|
||||
|
||||
# Add package signing certificate to the key chain
|
||||
import_certificate "Developer ID Installer" "${CFD_INSTALLER_CERT}" "${INSTALLER_CERT}"
|
||||
|
||||
# get the code signing certificate name
|
||||
if [[ ! -z "$CFD_CODE_SIGN_NAME" ]]; then
|
||||
CODE_SIGN_NAME="${CFD_CODE_SIGN_NAME}"
|
||||
else
|
||||
if [[ -n "$(security find-certificate -c "Developer ID Application" cloudflared_build_keychain | cut -d'"' -f 4 -s | grep "Developer ID Application:" | head -1)" ]]; then
|
||||
CODE_SIGN_NAME=$(security find-certificate -c "Developer ID Application" cloudflared_build_keychain | cut -d'"' -f 4 -s | grep "Developer ID Application:" | head -1)
|
||||
else
|
||||
CODE_SIGN_NAME=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# get the package signing certificate name
|
||||
if [[ ! -z "$CFD_INSTALLER_NAME" ]]; then
|
||||
PKG_SIGN_NAME="${CFD_INSTALLER_NAME}"
|
||||
else
|
||||
if [[ -n "$(security find-certificate -c "Developer ID Installer" cloudflared_build_keychain | cut -d'"' -f 4 -s | grep "Developer ID Installer:" | head -1)" ]]; then
|
||||
PKG_SIGN_NAME=$(security find-certificate -c "Developer ID Installer" cloudflared_build_keychain | cut -d'"' -f 4 -s | grep "Developer ID Installer:" | head -1)
|
||||
else
|
||||
PKG_SIGN_NAME=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# cleanup the build directory because the previous execution might have failed without cleaning up.
|
||||
rm -rf "${TARGET_DIRECTORY}"
|
||||
export TARGET_OS="darwin"
|
||||
GOCACHE="$PWD/../../../../" GOPATH="$PWD/../../../../" CGO_ENABLED=1 make cloudflared
|
||||
|
||||
|
||||
# This allows apple tools to use the certificates in the keychain without requiring password input.
|
||||
# This command always needs to run after the certificates have been loaded into the keychain
|
||||
if [[ ! -z "$CFD_CODE_SIGN_PASS" ]]; then
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k "${CFD_CODE_SIGN_PASS}" cloudflared_build_keychain
|
||||
fi
|
||||
|
||||
# sign the cloudflared binary
|
||||
if [[ ! -z "$CODE_SIGN_NAME" ]]; then
|
||||
codesign --keychain $HOME/Library/Keychains/cloudflared_build_keychain.keychain-db -s "${CODE_SIGN_NAME}" -fv --options runtime --timestamp ${BINARY_NAME}
|
||||
|
||||
# notarize the binary
|
||||
# TODO: TUN-5789
|
||||
fi
|
||||
|
||||
ARCH_TARGET_DIRECTORY="${TARGET_DIRECTORY}/${TARGET_ARCH}-build"
|
||||
# creating build directory
|
||||
rm -rf $ARCH_TARGET_DIRECTORY
|
||||
mkdir -p "${ARCH_TARGET_DIRECTORY}"
|
||||
mkdir -p "${ARCH_TARGET_DIRECTORY}/contents"
|
||||
cp -r ".mac_resources/scripts" "${ARCH_TARGET_DIRECTORY}/scripts"
|
||||
|
||||
# copy cloudflared into the build directory
|
||||
cp ${BINARY_NAME} "${ARCH_TARGET_DIRECTORY}/contents/${PRODUCT}"
|
||||
|
||||
# compress cloudflared into a tar and gzipped file
|
||||
tar czf "$FILENAME" "${BINARY_NAME}"
|
||||
|
||||
# build the installer package
|
||||
if [[ ! -z "$PKG_SIGN_NAME" ]]; then
|
||||
|
||||
pkgbuild --identifier com.cloudflare.${PRODUCT} \
|
||||
--version ${VERSION} \
|
||||
--scripts ${ARCH_TARGET_DIRECTORY}/scripts \
|
||||
--root ${ARCH_TARGET_DIRECTORY}/contents \
|
||||
--install-location /usr/local/bin \
|
||||
--keychain cloudflared_build_keychain \
|
||||
--sign "${PKG_SIGN_NAME}" \
|
||||
${PKGNAME}
|
||||
|
||||
# notarize the package
|
||||
# TODO: TUN-5789
|
||||
else
|
||||
pkgbuild --identifier com.cloudflare.${PRODUCT} \
|
||||
--version ${VERSION} \
|
||||
--scripts ${ARCH_TARGET_DIRECTORY}/scripts \
|
||||
--root ${ARCH_TARGET_DIRECTORY}/contents \
|
||||
--install-location /usr/local/bin \
|
||||
${PKGNAME}
|
||||
fi
|
||||
|
||||
# cleanup build directory because this script is not ran within containers,
|
||||
# which might lead to future issues in subsequent runs.
|
||||
rm -rf "${TARGET_DIRECTORY}"
|
||||
|
||||
# cleanup the keychain
|
||||
security default-keychain -d user -s login.keychain-db
|
||||
security list-keychains -d user -s login.keychain-db
|
||||
security delete-keychain cloudflared_build_keychain
|
||||
10
.ci/scripts/mac/install-go.sh
Executable file
10
.ci/scripts/mac/install-go.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
rm -rf /tmp/go
|
||||
export GOCACHE=/tmp/gocache
|
||||
rm -rf $GOCACHE
|
||||
|
||||
brew install go@1.24
|
||||
|
||||
go version
|
||||
which go
|
||||
go env
|
||||
|
||||
23
.ci/scripts/package-windows.sh
Executable file
23
.ci/scripts/package-windows.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
python3 -m venv env
|
||||
. env/bin/activate
|
||||
pip install pynacl==1.4.0 pygithub==1.55
|
||||
|
||||
VERSION=$(git describe --tags --always --match "[0-9][0-9][0-9][0-9].*.*")
|
||||
echo $VERSION
|
||||
|
||||
export TARGET_OS=windows
|
||||
# This controls the directory the built artifacts go into
|
||||
export BUILT_ARTIFACT_DIR=artifacts/
|
||||
export FINAL_ARTIFACT_DIR=artifacts/
|
||||
mkdir -p $BUILT_ARTIFACT_DIR
|
||||
mkdir -p $FINAL_ARTIFACT_DIR
|
||||
windowsArchs=("amd64" "386")
|
||||
for arch in ${windowsArchs[@]}; do
|
||||
export TARGET_ARCH=$arch
|
||||
# Copy .exe from artifacts directory
|
||||
cp $BUILT_ARTIFACT_DIR/cloudflared-windows-$arch.exe ./cloudflared.exe
|
||||
make cloudflared-msi
|
||||
# Copy msi into final directory
|
||||
mv cloudflared-$VERSION-$arch.msi $FINAL_ARTIFACT_DIR/cloudflared-windows-$arch.msi
|
||||
done
|
||||
24
.ci/scripts/windows/builds.ps1
Normal file
24
.ci/scripts/windows/builds.ps1
Normal file
@@ -0,0 +1,24 @@
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
$env:TARGET_OS = "windows"
|
||||
$env:LOCAL_OS = "windows"
|
||||
|
||||
New-Item -Path ".\artifacts" -ItemType Directory
|
||||
|
||||
Write-Output "Building for amd64"
|
||||
$env:TARGET_ARCH = "amd64"
|
||||
$env:LOCAL_ARCH = "amd64"
|
||||
$env:CGO_ENABLED = 1
|
||||
& make cloudflared
|
||||
if ($LASTEXITCODE -ne 0) { throw "Failed to build cloudflared for amd64" }
|
||||
copy .\cloudflared.exe .\artifacts\cloudflared-windows-amd64.exe
|
||||
|
||||
Write-Output "Building for 386"
|
||||
$env:TARGET_ARCH = "386"
|
||||
$env:LOCAL_ARCH = "386"
|
||||
$env:CGO_ENABLED = 0
|
||||
& make cloudflared
|
||||
if ($LASTEXITCODE -ne 0) { throw "Failed to build cloudflared for 386" }
|
||||
copy .\cloudflared.exe .\artifacts\cloudflared-windows-386.exe
|
||||
40
.ci/scripts/windows/component-test.ps1
Normal file
40
.ci/scripts/windows/component-test.ps1
Normal file
@@ -0,0 +1,40 @@
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
$env:TARGET_OS = "windows"
|
||||
$env:LOCAL_OS = "windows"
|
||||
$env:TARGET_ARCH = "amd64"
|
||||
$env:LOCAL_ARCH = "amd64"
|
||||
$env:CGO_ENABLED = 1
|
||||
|
||||
python --version
|
||||
python -m pip --version
|
||||
|
||||
|
||||
Write-Host "Building cloudflared"
|
||||
& make cloudflared
|
||||
if ($LASTEXITCODE -ne 0) { throw "Failed to build cloudflared" }
|
||||
|
||||
|
||||
Write-Host "Running unit tests"
|
||||
# Not testing with race detector because of https://github.com/golang/go/issues/61058
|
||||
# We already test it on other platforms
|
||||
go test -failfast -v -mod=vendor ./...
|
||||
if ($LASTEXITCODE -ne 0) { throw "Failed unit tests" }
|
||||
|
||||
|
||||
# On Gitlab runners we need to add all of this addresses to the NO_PROXY list in order for the tests to run.
|
||||
$env:NO_PROXY = "pypi.org,files.pythonhosted.org,api.cloudflare.com,argotunneltest.com,argotunnel.com,trycloudflare.com,${env:NO_PROXY}"
|
||||
Write-Host "No Proxy: ${env:NO_PROXY}"
|
||||
Write-Host "Running component tests"
|
||||
try {
|
||||
python -m pip --disable-pip-version-check install --upgrade -r component-tests/requirements.txt --use-pep517
|
||||
python component-tests/setup.py --type create
|
||||
python -m pytest component-tests -o log_cli=true --log-cli-level=INFO
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed component tests"
|
||||
}
|
||||
} finally {
|
||||
python component-tests/setup.py --type cleanup
|
||||
}
|
||||
69
.ci/scripts/windows/go-wrapper.ps1
Normal file
69
.ci/scripts/windows/go-wrapper.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
Param(
|
||||
[string]$GoVersion,
|
||||
[string]$ScriptToExecute
|
||||
)
|
||||
|
||||
# This script its a wrapper that downloads a specific version
|
||||
# of go, adds it to the PATH and executes a script with that go
|
||||
# version in the path.
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
# Get the path to the system's temporary directory.
|
||||
$tempPath = [System.IO.Path]::GetTempPath()
|
||||
|
||||
# Create a unique name for the new temporary folder.
|
||||
$folderName = "go_" + (Get-Random)
|
||||
|
||||
# Join the temp path and the new folder name to create the full path.
|
||||
$fullPath = Join-Path -Path $tempPath -ChildPath $folderName
|
||||
|
||||
# Store the current value of PATH environment variable.
|
||||
$oldPath = $env:Path
|
||||
|
||||
# Use a try...finally block to ensure the temporrary folder and PATH are cleaned up.
|
||||
try {
|
||||
# Create the temporary folder.
|
||||
Write-Host "Creating temporary folder at: $fullPath"
|
||||
$newTempFolder = New-Item -ItemType Directory -Path $fullPath -Force
|
||||
|
||||
# Download go
|
||||
$url = "https://go.dev/dl/$GoVersion.windows-amd64.zip"
|
||||
$destinationFile = Join-Path -Path $newTempFolder.FullName -ChildPath "go$GoVersion.windows-amd64.zip"
|
||||
Write-Host "Downloading go from: $url"
|
||||
Invoke-WebRequest -Uri $url -OutFile $destinationFile
|
||||
Write-Host "File downloaded to: $destinationFile"
|
||||
|
||||
# Unzip the downloaded file.
|
||||
Write-Host "Unzipping the file..."
|
||||
Expand-Archive -Path $destinationFile -DestinationPath $newTempFolder.FullName -Force
|
||||
Write-Host "File unzipped successfully."
|
||||
|
||||
# Define the go/bin path wich is inside the temporary folder
|
||||
$goBinPath = Join-Path -Path $fullPath -ChildPath "go\bin"
|
||||
|
||||
# Add the go/bin path to the PATH environment variable.
|
||||
$env:Path = "$goBinPath;$($env:Path)"
|
||||
Write-Host "Added $goBinPath to the environment PATH."
|
||||
|
||||
go env
|
||||
go version
|
||||
|
||||
& $ScriptToExecute
|
||||
} finally {
|
||||
# Cleanup: Remove the path from the environment variable and then the temporary folder.
|
||||
Write-Host "Starting cleanup..."
|
||||
|
||||
$env:Path = $oldPath
|
||||
Write-Host "Reverted changes in the environment PATH."
|
||||
|
||||
# Remove the temporary folder and its contents.
|
||||
if (Test-Path -Path $fullPath) {
|
||||
Remove-Item -Path $fullPath -Recurse -Force
|
||||
Write-Host "Temporary folder and its contents have been removed."
|
||||
} else {
|
||||
Write-Host "Temporary folder does not exist, no cleanup needed."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user