From e738ff5299091bf7580a6230ea59ea736fa149a3 Mon Sep 17 00:00:00 2001 From: Ethan <39577870+ethanndickson@users.noreply.github.com> Date: Thu, 5 Mar 2026 01:50:50 +1100 Subject: [PATCH] ci: remove dylib build pipeline (#22592) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary The macOS `.dylib` is only used by Coder Desktop macOS v0.7.2 or older. v0.7.2 was released in August 2025. v0.8.0 of Coder Desktop macOS, also released in August 2025, uses a signed Coder slim binary from the deployment instead. It's unlikely customers will be using Coder Desktop macOS v0.7.2 and the next release of Coder simultaneously, so I think we can safely remove this process, given it slows down CI & release processes. ## Changes - **Makefile**: Remove `DYLIB_ARCHES`, `CODER_DYLIBS` variables and `build/coder-dylib` target - **scripts/build_go.sh**: Remove `--dylib` flag and all dylib-specific logic (c-shared buildmode, CGO, plist embedding, vpn/dylib entrypoint) - **scripts/sign_darwin.sh**: Remove dylib-specific comment - **CI (ci.yaml)**: Remove `build-dylib` job, artifact download/insert steps, and `build-dylib` dependency from `build` job - **Release (release.yaml)**: Remove `build-dylib` job, artifact download/insert steps, and `build-dylib` dependency from `release` job - **vpn/dylib/**: Delete entire directory (`lib.go` + `info.plist.tmpl`) - **vpn/router.go, vpn/dns.go**: Clean up comments referencing dylib The slim and fat binary builds are completely unaffected — the dylib was an independent build target with its own CI job. _Generated by mux but reviewed by a human_ --- .github/workflows/ci.yaml | 95 +----------------------------- .github/workflows/deploy-docs.yaml | 2 + .github/workflows/release.yaml | 92 +---------------------------- Makefile | 24 -------- scripts/build_go.sh | 35 +---------- scripts/sign_darwin.sh | 1 - vpn/dns.go | 2 +- vpn/dylib/info.plist.tmpl | 14 ----- vpn/dylib/lib.go | 64 -------------------- vpn/router.go | 2 +- 10 files changed, 10 insertions(+), 321 deletions(-) delete mode 100644 vpn/dylib/info.plist.tmpl delete mode 100644 vpn/dylib/lib.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2b1679cb65..48ca6ade61 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1038,83 +1038,6 @@ jobs: echo "Required checks have passed" - # Builds the dylibs and upload it as an artifact so it can be embedded in the main build - build-dylib: - needs: changes - # We always build the dylibs on Go changes to verify we're not merging unbuildable code, - # but they need only be signed and uploaded on coder/coder main. - if: needs.changes.outputs.go == 'true' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') - runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest' }} - steps: - # Harden Runner doesn't work on macOS - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Setup GNU tools (macOS) - uses: ./.github/actions/setup-gnu-tools - - - name: Switch XCode Version - uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 - with: - xcode-version: "16.1.0" - - - name: Setup Go - uses: ./.github/actions/setup-go - - - name: Install rcodesign - if: ${{ github.repository_owner == 'coder' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) }} - run: | - set -euo pipefail - wget -O /tmp/rcodesign.tar.gz https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-macos-universal.tar.gz - sudo tar -xzf /tmp/rcodesign.tar.gz \ - -C /usr/local/bin \ - --strip-components=1 \ - apple-codesign-0.22.0-macos-universal/rcodesign - rm /tmp/rcodesign.tar.gz - - - name: Setup Apple Developer certificate and API key - if: ${{ github.repository_owner == 'coder' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) }} - run: | - set -euo pipefail - touch /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} - chmod 600 /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} - echo "$AC_CERTIFICATE_P12_BASE64" | base64 -d > /tmp/apple_cert.p12 - echo "$AC_CERTIFICATE_PASSWORD" > /tmp/apple_cert_password.txt - echo "$AC_APIKEY_P8_BASE64" | base64 -d > /tmp/apple_apikey.p8 - env: - AC_CERTIFICATE_P12_BASE64: ${{ secrets.AC_CERTIFICATE_P12_BASE64 }} - AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }} - AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }} - - - name: Build dylibs - run: | - set -euxo pipefail - ./.github/scripts/retry.sh -- go mod download - - make gen/mark-fresh - make build/coder-dylib - env: - CODER_SIGN_DARWIN: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && '1' || '0' }} - AC_CERTIFICATE_FILE: /tmp/apple_cert.p12 - AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt - - - name: Upload build artifacts - if: ${{ github.repository_owner == 'coder' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) }} - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 - with: - name: dylibs - path: | - ./build/*.h - ./build/*.dylib - retention-days: 7 - - - name: Delete Apple Developer certificate and API key - if: ${{ github.repository_owner == 'coder' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) }} - run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} - check-build: # This job runs make build to verify compilation on PRs. # The build doesn't get signed, and is not suitable for usage, unlike the @@ -1161,7 +1084,6 @@ jobs: # to main branch. needs: - changes - - build-dylib if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && needs.changes.outputs.docs-only == 'false' && !github.event.pull_request.head.repo.fork runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-22.04' }} permissions: @@ -1267,18 +1189,6 @@ jobs: - name: Setup GCloud SDK uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1 - - name: Download dylibs - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - with: - name: dylibs - path: ./build - - - name: Insert dylibs - run: | - mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib - mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib - mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h - - name: Build run: | set -euxo pipefail @@ -1294,9 +1204,8 @@ jobs: build/coder_"$version"_windows_amd64.zip \ build/coder_"$version"_linux_amd64.{tar.gz,deb} env: - # The Windows slim binary must be signed for Coder Desktop to accept - # it. The darwin executables don't need to be signed, but the dylibs - # do (see above). + # The Windows and Darwin slim binaries must be signed for Coder + # Desktop to accept them. CODER_SIGN_WINDOWS: "1" CODER_WINDOWS_RESOURCES: "1" CODER_SIGN_GPG: "1" diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml index a3b1682c04..41c6e35bda 100644 --- a/.github/workflows/deploy-docs.yaml +++ b/.github/workflows/deploy-docs.yaml @@ -12,6 +12,8 @@ on: paths: - "docs/manifest.json" +permissions: {} + jobs: deploy-docs: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0e45b93bf7..52c348bc08 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -58,87 +58,9 @@ jobs: if (!allowed) core.setFailed('Denied: requires maintain or admin'); - # build-dylib is a separate job to build the dylib on macOS. - build-dylib: - runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest' }} - needs: check-perms - steps: - # Harden Runner doesn't work on macOS. - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - persist-credentials: false - - # If the event that triggered the build was an annotated tag (which our - # tags are supposed to be), actions/checkout has a bug where the tag in - # question is only a lightweight tag and not a full annotated tag. This - # command seems to fix it. - # https://github.com/actions/checkout/issues/290 - - name: Fetch git tags - run: git fetch --tags --force - - - name: Setup GNU tools (macOS) - uses: ./.github/actions/setup-gnu-tools - - - name: Switch XCode Version - uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 - with: - xcode-version: "16.1.0" - - - name: Setup Go - uses: ./.github/actions/setup-go - - - name: Install rcodesign - run: | - set -euo pipefail - wget -O /tmp/rcodesign.tar.gz https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-macos-universal.tar.gz - sudo tar -xzf /tmp/rcodesign.tar.gz \ - -C /usr/local/bin \ - --strip-components=1 \ - apple-codesign-0.22.0-macos-universal/rcodesign - rm /tmp/rcodesign.tar.gz - - - name: Setup Apple Developer certificate and API key - run: | - set -euo pipefail - touch /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} - chmod 600 /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} - echo "$AC_CERTIFICATE_P12_BASE64" | base64 -d > /tmp/apple_cert.p12 - echo "$AC_CERTIFICATE_PASSWORD" > /tmp/apple_cert_password.txt - echo "$AC_APIKEY_P8_BASE64" | base64 -d > /tmp/apple_apikey.p8 - env: - AC_CERTIFICATE_P12_BASE64: ${{ secrets.AC_CERTIFICATE_P12_BASE64 }} - AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }} - AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }} - - - name: Build dylibs - run: | - set -euxo pipefail - ./.github/scripts/retry.sh -- go mod download - - make gen/mark-fresh - make build/coder-dylib - env: - CODER_SIGN_DARWIN: 1 - AC_CERTIFICATE_FILE: /tmp/apple_cert.p12 - AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt - - - name: Upload build artifacts - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 - with: - name: dylibs - path: | - ./build/*.h - ./build/*.dylib - retention-days: 7 - - - name: Delete Apple Developer certificate and API key - run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} - release: name: Build and publish - needs: [build-dylib, check-perms] + needs: [check-perms] runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }} permissions: # Required to publish a release @@ -320,18 +242,6 @@ jobs: - name: Setup GCloud SDK uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1 - - name: Download dylibs - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - with: - name: dylibs - path: ./build - - - name: Insert dylibs - run: | - mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib - mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib - mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h - - name: Build binaries run: | set -euo pipefail diff --git a/Makefile b/Makefile index 3d52b6f7a6..88c6ed5eba 100644 --- a/Makefile +++ b/Makefile @@ -94,12 +94,8 @@ PACKAGE_OS_ARCHES := linux_amd64 linux_armv7 linux_arm64 # All architectures we build Docker images for (Linux only). DOCKER_ARCHES := amd64 arm64 armv7 -# All ${OS}_${ARCH} combos we build the desktop dylib for. -DYLIB_ARCHES := darwin_amd64 darwin_arm64 - # Computed variables based on the above. CODER_SLIM_BINARIES := $(addprefix build/coder-slim_$(VERSION)_,$(OS_ARCHES)) -CODER_DYLIBS := $(foreach os_arch, $(DYLIB_ARCHES), build/coder-vpn_$(VERSION)_$(os_arch).dylib) CODER_FAT_BINARIES := $(addprefix build/coder_$(VERSION)_,$(OS_ARCHES)) CODER_ALL_BINARIES := $(CODER_SLIM_BINARIES) $(CODER_FAT_BINARIES) CODER_TAR_GZ_ARCHIVES := $(foreach os_arch, $(ARCHIVE_TAR_GZ), build/coder_$(VERSION)_$(os_arch).tar.gz) @@ -261,26 +257,6 @@ $(CODER_ALL_BINARIES): go.mod go.sum \ fi fi -# This task builds Coder Desktop dylibs -$(CODER_DYLIBS): go.mod go.sum $(MOST_GO_SRC_FILES) - @if [ "$(shell uname)" = "Darwin" ]; then - $(get-mode-os-arch-ext) - ./scripts/build_go.sh \ - --os "$$os" \ - --arch "$$arch" \ - --version "$(VERSION)" \ - --output "$@" \ - --dylib - - else - echo "ERROR: Can't build dylib on non-Darwin OS" 1>&2 - exit 1 - fi - -# This task builds both dylibs -build/coder-dylib: $(CODER_DYLIBS) -.PHONY: build/coder-dylib - # This task builds all archives. It parses the target name to get the metadata # for the build, so it must be specified in this format: # build/coder_${version}_${os}_${arch}.${format} diff --git a/scripts/build_go.sh b/scripts/build_go.sh index e291d5fc29..40aff19ad0 100755 --- a/scripts/build_go.sh +++ b/scripts/build_go.sh @@ -2,7 +2,7 @@ # This script builds a single Go binary of Coder with the given parameters. # -# Usage: ./build_go.sh [--version 1.2.3-devel+abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim] [--agpl] [--boringcrypto] [--dylib] +# Usage: ./build_go.sh [--version 1.2.3-devel+abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim] [--agpl] [--boringcrypto] # # Defaults to linux:amd64 with slim disabled, but can be controlled with GOOS, # GOARCH and CODER_SLIM_BUILD=1. If no version is specified, defaults to the @@ -29,9 +29,6 @@ # If the --boringcrypto parameter is specified, builds use boringcrypto instead of # the standard go crypto libraries. # -# If the --dylib parameter is specified, the Coder Desktop `.dylib` is built -# instead of the standard binary. This is only supported on macOS arm64 & amd64. - set -euo pipefail # shellcheck source=scripts/lib.sh source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" @@ -46,14 +43,13 @@ sign_darwin="${CODER_SIGN_DARWIN:-0}" sign_windows="${CODER_SIGN_WINDOWS:-0}" sign_gpg="${CODER_SIGN_GPG:-0}" boringcrypto=${CODER_BUILD_BORINGCRYPTO:-0} -dylib=0 windows_resources="${CODER_WINDOWS_RESOURCES:-0}" debug=0 develop_in_coder="${DEVELOP_IN_CODER:-0}" bin_ident="com.coder.cli" -args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,sign-windows,boringcrypto,dylib,windows-resources,debug -- "$@")" +args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,sign-windows,boringcrypto,windows-resources,debug -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -98,10 +94,6 @@ while true; do boringcrypto=1 shift ;; - --dylib) - dylib=1 - shift - ;; --windows-resources) windows_resources=1 shift @@ -160,7 +152,7 @@ fi # We use ts_omit_aws here because on Linux it prevents Tailscale from importing # github.com/aws/aws-sdk-go-v2/aws, which adds 7 MB to the binary. TS_EXTRA_SMALL="ts_omit_aws,ts_omit_bird,ts_omit_tap,ts_omit_kube" -if [[ "$slim" == 1 || "$dylib" == 1 ]]; then +if [[ "$slim" == 1 ]]; then build_args+=(-tags "slim,$TS_EXTRA_SMALL") else build_args+=(-tags "embed,$TS_EXTRA_SMALL") @@ -171,24 +163,6 @@ if [[ "$agpl" == 1 ]]; then ldflags+=(-X "'github.com/coder/coder/v2/buildinfo.agpl=true'") fi cgo=0 -if [[ "$dylib" == 1 ]]; then - if [[ "$os" != "darwin" ]]; then - error "dylib builds are not supported on $os" - fi - cgo=1 - build_args+=("-buildmode=c-shared") - SDKROOT="$(xcrun --sdk macosx --show-sdk-path)" - export SDKROOT - bin_ident="com.coder.Coder-Desktop.VPN.dylib" - - plist_file=$(mktemp) - trap 'rm -f "$plist_file"' EXIT - # CFBundleShortVersionString must be in the format /[0-9]+.[0-9]+.[0-9]+/ - # CFBundleVersion can be in any format - BUNDLE_IDENTIFIER="$bin_ident" VERSION_STRING="$version" SHORT_VERSION_STRING=$(echo "$version" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') \ - execrelative envsubst <"$(realpath ./vpn/dylib/info.plist.tmpl)" >"$plist_file" - ldflags+=("-extldflags '-sectcreate __TEXT __info_plist $plist_file'") -fi build_args+=(-ldflags "${ldflags[*]}") # Disable optimizations if building a binary for debuggers. @@ -222,9 +196,6 @@ cmd_path="./enterprise/cmd/coder" if [[ "$agpl" == 1 ]]; then cmd_path="./cmd/coder" fi -if [[ "$dylib" == 1 ]]; then - cmd_path="./vpn/dylib/lib.go" -fi goexp="" if [[ "$boringcrypto" == 1 ]]; then diff --git a/scripts/sign_darwin.sh b/scripts/sign_darwin.sh index dce1499f33..068b193da8 100755 --- a/scripts/sign_darwin.sh +++ b/scripts/sign_darwin.sh @@ -9,7 +9,6 @@ # certificate. # # For the Coder CLI, the binary_identifier should be "com.coder.cli". -# For the CoderVPN `.dylib`, the binary_identifier should be "com.coder.Coder-Desktop.VPN.dylib". # # You can check if a binary is signed by running the following command on a Mac: # codesign -dvv path/to/binary diff --git a/vpn/dns.go b/vpn/dns.go index 7e4ea5bbd2..6ff606ec91 100644 --- a/vpn/dns.go +++ b/vpn/dns.go @@ -31,7 +31,7 @@ func (*dnsManager) SupportsSplitDNS() bool { // Close implements dns.OSConfigurator. func (*dnsManager) Close() error { - // There's no cleanup that we need to initiate from within the dylib. + // There's no cleanup that we need to initiate from within the tunnel. return nil } diff --git a/vpn/dylib/info.plist.tmpl b/vpn/dylib/info.plist.tmpl deleted file mode 100644 index caf9cfa575..0000000000 --- a/vpn/dylib/info.plist.tmpl +++ /dev/null @@ -1,14 +0,0 @@ - - - - - CFBundleName - CoderVPN - CFBundleIdentifier - ${BUNDLE_IDENTIFIER} - CFBundleVersion - ${VERSION_STRING} - CFBundleShortVersionString - ${SHORT_VERSION_STRING} - - diff --git a/vpn/dylib/lib.go b/vpn/dylib/lib.go deleted file mode 100644 index 35d2d8d5cb..0000000000 --- a/vpn/dylib/lib.go +++ /dev/null @@ -1,64 +0,0 @@ -//go:build darwin - -package main - -import "C" - -import ( - "context" - - "golang.org/x/sys/unix" - - "cdr.dev/slog/v3" - "github.com/coder/coder/v2/vpn" -) - -const ( - ErrDupReadFD = -2 - ErrDupWriteFD = -3 - ErrOpenPipe = -4 - ErrNewTunnel = -5 -) - -// OpenTunnel creates a new VPN tunnel by `dup`ing the provided 'PIPE' -// file descriptors for reading and writing. -// -//export OpenTunnel -func OpenTunnel(cReadFD, cWriteFD int32) int32 { - ctx := context.Background() - - readFD, err := unix.Dup(int(cReadFD)) - if err != nil { - return ErrDupReadFD - } - - writeFD, err := unix.Dup(int(cWriteFD)) - if err != nil { - unix.Close(readFD) - return ErrDupWriteFD - } - - conn, err := vpn.NewBidirectionalPipe(uintptr(readFD), uintptr(writeFD)) - if err != nil { - unix.Close(readFD) - unix.Close(writeFD) - return ErrOpenPipe - } - - // We log everything, as filtering is done by whatever renders the OS - // logs. - _, err = vpn.NewTunnel(ctx, slog.Make().Leveled(slog.LevelDebug), conn, - vpn.NewClient(), - vpn.UseOSNetworkingStack(), - vpn.UseAsLogger(), - ) - if err != nil { - unix.Close(readFD) - unix.Close(writeFD) - return ErrNewTunnel - } - - return 0 -} - -func main() {} diff --git a/vpn/router.go b/vpn/router.go index a3fab4bf9b..545b96a758 100644 --- a/vpn/router.go +++ b/vpn/router.go @@ -30,7 +30,7 @@ func (v *vpnRouter) Set(cfg *router.Config) error { } func (*vpnRouter) Close() error { - // There's no cleanup that we need to initiate from within the dylib. + // There's no cleanup that we need to initiate from within the tunnel. return nil }