Skip to content

Commit ebcf687

Browse files
committed
merge main
2 parents 3aa81ed + dcbcf67 commit ebcf687

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1386
-221
lines changed

.github/workflows/ci.yaml

+94-1
Original file line numberDiff line numberDiff line change
@@ -806,10 +806,91 @@ jobs:
806806
807807
echo "Required checks have passed"
808808
809+
# Builds the dylibs and upload it as an artifact so it can be embedded in the main build
810+
build-dylib:
811+
needs: changes
812+
# We always build the dylibs on Go changes to verify we're not merging unbuildable code,
813+
# but they need only be signed and uploaded on coder/coder main.
814+
if: needs.changes.outputs.docs-only == 'false' || github.ref == 'refs/heads/main'
815+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest' }}
816+
steps:
817+
- name: Harden Runner
818+
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
819+
with:
820+
egress-policy: audit
821+
822+
- name: Checkout
823+
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
824+
with:
825+
fetch-depth: 0
826+
827+
- name: Setup build tools
828+
run: |
829+
brew install bash gnu-getopt make
830+
echo "$(brew --prefix bash)/bin" >> $GITHUB_PATH
831+
echo "$(brew --prefix gnu-getopt)/bin" >> $GITHUB_PATH
832+
echo "$(brew --prefix make)/libexec/gnubin" >> $GITHUB_PATH
833+
834+
- name: Setup Go
835+
uses: ./.github/actions/setup-go
836+
837+
- name: Install rcodesign
838+
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
839+
run: |
840+
set -euo pipefail
841+
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
842+
sudo tar -xzf /tmp/rcodesign.tar.gz \
843+
-C /usr/local/bin \
844+
--strip-components=1 \
845+
apple-codesign-0.22.0-macos-universal/rcodesign
846+
rm /tmp/rcodesign.tar.gz
847+
848+
- name: Setup Apple Developer certificate and API key
849+
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
850+
run: |
851+
set -euo pipefail
852+
touch /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
853+
chmod 600 /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
854+
echo "$AC_CERTIFICATE_P12_BASE64" | base64 -d > /tmp/apple_cert.p12
855+
echo "$AC_CERTIFICATE_PASSWORD" > /tmp/apple_cert_password.txt
856+
echo "$AC_APIKEY_P8_BASE64" | base64 -d > /tmp/apple_apikey.p8
857+
env:
858+
AC_CERTIFICATE_P12_BASE64: ${{ secrets.AC_CERTIFICATE_P12_BASE64 }}
859+
AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }}
860+
AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }}
861+
862+
- name: Build dylibs
863+
run: |
864+
set -euxo pipefail
865+
go mod download
866+
867+
make gen/mark-fresh
868+
make build/coder-dylib
869+
env:
870+
CODER_SIGN_DARWIN: ${{ github.ref == 'refs/heads/main' && '1' || '0' }}
871+
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
872+
AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt
873+
874+
- name: Upload build artifacts
875+
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
876+
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
877+
with:
878+
name: dylibs
879+
path: |
880+
./build/*.h
881+
./build/*.dylib
882+
retention-days: 7
883+
884+
- name: Delete Apple Developer certificate and API key
885+
if: ${{ github.repository_owner == 'coder' && github.ref == 'refs/heads/main' }}
886+
run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
887+
809888
build:
810889
# This builds and publishes ghcr.io/coder/coder-preview:main for each commit
811890
# to main branch.
812-
needs: changes
891+
needs:
892+
- changes
893+
- build-dylib
813894
if: github.ref == 'refs/heads/main' && needs.changes.outputs.docs-only == 'false' && !github.event.pull_request.head.repo.fork
814895
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
815896
permissions:
@@ -848,6 +929,18 @@ jobs:
848929
- name: Install zstd
849930
run: sudo apt-get install -y zstd
850931

932+
- name: Download dylibs
933+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
934+
with:
935+
name: dylibs
936+
path: ./build
937+
938+
- name: Insert dylibs
939+
run: |
940+
mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib
941+
mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib
942+
mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h
943+
851944
- name: Build
852945
run: |
853946
set -euxo pipefail

.github/workflows/release.yaml

+89-4
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,80 @@ env:
3232
CODER_RELEASE_NOTES: ${{ inputs.release_notes }}
3333

3434
jobs:
35+
# build-dylib is a separate job to build the dylib on macOS.
36+
build-dylib:
37+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest' }}
38+
steps:
39+
- name: Harden Runner
40+
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
41+
with:
42+
egress-policy: audit
43+
44+
- name: Checkout
45+
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
46+
with:
47+
fetch-depth: 0
48+
49+
- name: Setup build tools
50+
run: |
51+
brew install bash gnu-getopt make
52+
echo "$(brew --prefix bash)/bin" >> $GITHUB_PATH
53+
echo "$(brew --prefix gnu-getopt)/bin" >> $GITHUB_PATH
54+
echo "$(brew --prefix make)/libexec/gnubin" >> $GITHUB_PATH
55+
56+
- name: Setup Go
57+
uses: ./.github/actions/setup-go
58+
59+
- name: Install rcodesign
60+
run: |
61+
set -euo pipefail
62+
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
63+
sudo tar -xzf /tmp/rcodesign.tar.gz \
64+
-C /usr/local/bin \
65+
--strip-components=1 \
66+
apple-codesign-0.22.0-macos-universal/rcodesign
67+
rm /tmp/rcodesign.tar.gz
68+
69+
- name: Setup Apple Developer certificate and API key
70+
run: |
71+
set -euo pipefail
72+
touch /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
73+
chmod 600 /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
74+
echo "$AC_CERTIFICATE_P12_BASE64" | base64 -d > /tmp/apple_cert.p12
75+
echo "$AC_CERTIFICATE_PASSWORD" > /tmp/apple_cert_password.txt
76+
echo "$AC_APIKEY_P8_BASE64" | base64 -d > /tmp/apple_apikey.p8
77+
env:
78+
AC_CERTIFICATE_P12_BASE64: ${{ secrets.AC_CERTIFICATE_P12_BASE64 }}
79+
AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }}
80+
AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }}
81+
82+
- name: Build dylibs
83+
run: |
84+
set -euxo pipefail
85+
go mod download
86+
87+
make gen/mark-fresh
88+
make build/coder-dylib
89+
env:
90+
CODER_SIGN_DARWIN: 1
91+
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
92+
AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt
93+
94+
- name: Upload build artifacts
95+
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
96+
with:
97+
name: dylibs
98+
path: |
99+
./build/*.h
100+
./build/*.dylib
101+
retention-days: 7
102+
103+
- name: Delete Apple Developer certificate and API key
104+
run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8}
105+
35106
release:
36107
name: Build and publish
108+
needs: build-dylib
37109
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
38110
permissions:
39111
# Required to publish a release
@@ -145,6 +217,18 @@ jobs:
145217
- name: Install nsis and zstd
146218
run: sudo apt-get install -y nsis zstd
147219

220+
- name: Download dylibs
221+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
222+
with:
223+
name: dylibs
224+
path: ./build
225+
226+
- name: Insert dylibs
227+
run: |
228+
mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib
229+
mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib
230+
mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h
231+
148232
- name: Install nfpm
149233
run: |
150234
set -euo pipefail
@@ -271,6 +355,7 @@ jobs:
271355
${{ steps.image-base-tag.outputs.tag }}
272356
273357
- name: Verify that images are pushed properly
358+
if: steps.image-base-tag.outputs.tag != ''
274359
run: |
275360
# retry 10 times with a 5 second delay as the images may not be
276361
# available immediately
@@ -303,17 +388,17 @@ jobs:
303388
run: |
304389
set -euxo pipefail
305390
306-
# build Docker images for each architecture
307-
version="$(./scripts/version.sh)"
308-
make build/coder_"$version"_linux_{amd64,arm64,armv7}.tag
309-
310391
# we can't build multi-arch if the images aren't pushed, so quit now
311392
# if dry-running
312393
if [[ "$CODER_RELEASE" != *t* ]]; then
313394
echo Skipping multi-arch docker builds due to dry-run.
314395
exit 0
315396
fi
316397
398+
# build Docker images for each architecture
399+
version="$(./scripts/version.sh)"
400+
make build/coder_"$version"_linux_{amd64,arm64,armv7}.tag
401+
317402
# build and push multi-arch manifest, this depends on the other images
318403
# being pushed so will automatically push them.
319404
make push/build/coder_"$version"_linux.tag

Makefile

+23
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,12 @@ PACKAGE_OS_ARCHES := linux_amd64 linux_armv7 linux_arm64
7979
# All architectures we build Docker images for (Linux only).
8080
DOCKER_ARCHES := amd64 arm64 armv7
8181

82+
# All ${OS}_${ARCH} combos we build the desktop dylib for.
83+
DYLIB_ARCHES := darwin_amd64 darwin_arm64
84+
8285
# Computed variables based on the above.
8386
CODER_SLIM_BINARIES := $(addprefix build/coder-slim_$(VERSION)_,$(OS_ARCHES))
87+
CODER_DYLIBS := $(foreach os_arch, $(DYLIB_ARCHES), build/coder-vpn_$(VERSION)_$(os_arch).dylib)
8488
CODER_FAT_BINARIES := $(addprefix build/coder_$(VERSION)_,$(OS_ARCHES))
8589
CODER_ALL_BINARIES := $(CODER_SLIM_BINARIES) $(CODER_FAT_BINARIES)
8690
CODER_TAR_GZ_ARCHIVES := $(foreach os_arch, $(ARCHIVE_TAR_GZ), build/coder_$(VERSION)_$(os_arch).tar.gz)
@@ -238,6 +242,25 @@ $(CODER_ALL_BINARIES): go.mod go.sum \
238242
cp "$@" "./site/out/bin/coder-$$os-$$arch$$dot_ext"
239243
fi
240244

245+
# This task builds Coder Desktop dylibs
246+
$(CODER_DYLIBS): go.mod go.sum $(GO_SRC_FILES)
247+
@if [ "$(shell uname)" = "Darwin" ]; then
248+
$(get-mode-os-arch-ext)
249+
./scripts/build_go.sh \
250+
--os "$$os" \
251+
--arch "$$arch" \
252+
--version "$(VERSION)" \
253+
--output "$@" \
254+
--dylib
255+
256+
else
257+
echo "ERROR: Can't build dylib on non-Darwin OS" 1>&2
258+
exit 1
259+
fi
260+
261+
# This task builds both dylibs
262+
build/coder-dylib: $(CODER_DYLIBS)
263+
241264
# This task builds all archives. It parses the target name to get the metadata
242265
# for the build, so it must be specified in this format:
243266
# build/coder_${version}_${os}_${arch}.${format}

cli/agent.go

+3-30
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"runtime"
1313
"strconv"
1414
"strings"
15-
"sync"
1615
"time"
1716

1817
"cloud.google.com/go/compute/metadata"
@@ -30,6 +29,7 @@ import (
3029
"github.com/coder/coder/v2/agent/agentssh"
3130
"github.com/coder/coder/v2/agent/reaper"
3231
"github.com/coder/coder/v2/buildinfo"
32+
"github.com/coder/coder/v2/cli/clilog"
3333
"github.com/coder/coder/v2/codersdk"
3434
"github.com/coder/coder/v2/codersdk/agentsdk"
3535
"github.com/coder/serpent"
@@ -110,7 +110,7 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
110110
// Spawn a reaper so that we don't accumulate a ton
111111
// of zombie processes.
112112
if reaper.IsInitProcess() && !noReap && isLinux {
113-
logWriter := &lumberjackWriteCloseFixer{w: &lumberjack.Logger{
113+
logWriter := &clilog.LumberjackWriteCloseFixer{Writer: &lumberjack.Logger{
114114
Filename: filepath.Join(logDir, "coder-agent-init.log"),
115115
MaxSize: 5, // MB
116116
// Without this, rotated logs will never be deleted.
@@ -153,7 +153,7 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
153153
// reaper.
154154
go DumpHandler(ctx, "agent")
155155

156-
logWriter := &lumberjackWriteCloseFixer{w: &lumberjack.Logger{
156+
logWriter := &clilog.LumberjackWriteCloseFixer{Writer: &lumberjack.Logger{
157157
Filename: filepath.Join(logDir, "coder-agent.log"),
158158
MaxSize: 5, // MB
159159
// Per customer incident on November 17th, 2023, its helpful
@@ -478,33 +478,6 @@ func ServeHandler(ctx context.Context, logger slog.Logger, handler http.Handler,
478478
}
479479
}
480480

481-
// lumberjackWriteCloseFixer is a wrapper around an io.WriteCloser that
482-
// prevents writes after Close. This is necessary because lumberjack
483-
// re-opens the file on Write.
484-
type lumberjackWriteCloseFixer struct {
485-
w io.WriteCloser
486-
mu sync.Mutex // Protects following.
487-
closed bool
488-
}
489-
490-
func (c *lumberjackWriteCloseFixer) Close() error {
491-
c.mu.Lock()
492-
defer c.mu.Unlock()
493-
494-
c.closed = true
495-
return c.w.Close()
496-
}
497-
498-
func (c *lumberjackWriteCloseFixer) Write(p []byte) (int, error) {
499-
c.mu.Lock()
500-
defer c.mu.Unlock()
501-
502-
if c.closed {
503-
return 0, io.ErrClosedPipe
504-
}
505-
return c.w.Write(p)
506-
}
507-
508481
// extractPort handles different url strings.
509482
// - localhost:6060
510483
// - http://localhost:6060

0 commit comments

Comments
 (0)