Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 36186bb

Browse files
feat: include winres metadata in Windows binaries (cherry-pick #16706) (#16742)
cherry picks #16706 to `release/2.20` --------- Co-authored-by: Dean Sheather <[email protected]>
1 parent 780b271 commit 36186bb

File tree

7 files changed

+185
-21
lines changed

7 files changed

+185
-21
lines changed

.github/workflows/ci.yaml

+50-3
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,10 @@ jobs:
10211021
if: github.ref == 'refs/heads/main' && needs.changes.outputs.docs-only == 'false' && !github.event.pull_request.head.repo.fork
10221022
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-22.04' }}
10231023
permissions:
1024-
packages: write # Needed to push images to ghcr.io
1024+
# Necessary to push docker images to ghcr.io.
1025+
packages: write
1026+
# Necessary for GCP authentication (https://github.com/google-github-actions/setup-gcloud#usage)
1027+
id-token: write
10251028
env:
10261029
DOCKER_CLI_EXPERIMENTAL: "enabled"
10271030
outputs:
@@ -1050,12 +1053,44 @@ jobs:
10501053
- name: Setup Go
10511054
uses: ./.github/actions/setup-go
10521055

1056+
# Necessary for signing Windows binaries.
1057+
- name: Setup Java
1058+
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0
1059+
with:
1060+
distribution: "zulu"
1061+
java-version: "11.0"
1062+
1063+
- name: Install go-winres
1064+
run: go install github.com/tc-hib/go-winres@d743268d7ea168077ddd443c4240562d4f5e8c3e # v0.3.3
1065+
10531066
- name: Install nfpm
10541067
run: go install github.com/goreleaser/nfpm/v2/cmd/[email protected]
10551068

10561069
- name: Install zstd
10571070
run: sudo apt-get install -y zstd
10581071

1072+
- name: Setup Windows EV Signing Certificate
1073+
run: |
1074+
set -euo pipefail
1075+
touch /tmp/ev_cert.pem
1076+
chmod 600 /tmp/ev_cert.pem
1077+
echo "$EV_SIGNING_CERT" > /tmp/ev_cert.pem
1078+
wget https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar -O /tmp/jsign-6.0.jar
1079+
env:
1080+
EV_SIGNING_CERT: ${{ secrets.EV_SIGNING_CERT }}
1081+
1082+
# Setup GCloud for signing Windows binaries.
1083+
- name: Authenticate to Google Cloud
1084+
id: gcloud_auth
1085+
uses: google-github-actions/auth@71f986410dfbc7added4569d411d040a91dc6935 # v2.1.8
1086+
with:
1087+
workload_identity_provider: ${{ secrets.GCP_CODE_SIGNING_WORKLOAD_ID_PROVIDER }}
1088+
service_account: ${{ secrets.GCP_CODE_SIGNING_SERVICE_ACCOUNT }}
1089+
token_format: "access_token"
1090+
1091+
- name: Setup GCloud SDK
1092+
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
1093+
10591094
- name: Download dylibs
10601095
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
10611096
with:
@@ -1082,6 +1117,18 @@ jobs:
10821117
build/coder_linux_{amd64,arm64,armv7} \
10831118
build/coder_"$version"_windows_amd64.zip \
10841119
build/coder_"$version"_linux_amd64.{tar.gz,deb}
1120+
env:
1121+
# The Windows slim binary must be signed for Coder Desktop to accept
1122+
# it. The darwin executables don't need to be signed, but the dylibs
1123+
# do (see above).
1124+
CODER_SIGN_WINDOWS: "1"
1125+
CODER_WINDOWS_RESOURCES: "1"
1126+
EV_KEY: ${{ secrets.EV_KEY }}
1127+
EV_KEYSTORE: ${{ secrets.EV_KEYSTORE }}
1128+
EV_TSA_URL: ${{ secrets.EV_TSA_URL }}
1129+
EV_CERTIFICATE_PATH: /tmp/ev_cert.pem
1130+
GCLOUD_ACCESS_TOKEN: ${{ steps.gcloud_auth.outputs.access_token }}
1131+
JSIGN_PATH: /tmp/jsign-6.0.jar
10851132

10861133
- name: Build Linux Docker images
10871134
id: build-docker
@@ -1183,10 +1230,10 @@ jobs:
11831230
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
11841231

11851232
- name: Set up Flux CLI
1186-
uses: fluxcd/flux2/action@af67405ee43a6cd66e0b73f4b3802e8583f9d961 # v2.5.0
1233+
uses: fluxcd/flux2/action@8d5f40dca5aa5d3c0fc3414457dda15a0ac92fa4 # v2.5.1
11871234
with:
11881235
# Keep this and the github action up to date with the version of flux installed in dogfood cluster
1189-
version: "2.2.1"
1236+
version: "2.5.1"
11901237

11911238
- name: Get Cluster Credentials
11921239
uses: google-github-actions/get-gke-credentials@7a108e64ed8546fe38316b4086e91da13f4785e1 # v2.3.1

.github/workflows/release.yaml

+16-12
Original file line numberDiff line numberDiff line change
@@ -223,21 +223,12 @@ jobs:
223223
distribution: "zulu"
224224
java-version: "11.0"
225225

226+
- name: Install go-winres
227+
run: go install github.com/tc-hib/go-winres@d743268d7ea168077ddd443c4240562d4f5e8c3e # v0.3.3
228+
226229
- name: Install nsis and zstd
227230
run: sudo apt-get install -y nsis zstd
228231

229-
- name: Download dylibs
230-
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
231-
with:
232-
name: dylibs
233-
path: ./build
234-
235-
- name: Insert dylibs
236-
run: |
237-
mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib
238-
mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib
239-
mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h
240-
241232
- name: Install nfpm
242233
run: |
243234
set -euo pipefail
@@ -294,6 +285,18 @@ jobs:
294285
- name: Setup GCloud SDK
295286
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
296287

288+
- name: Download dylibs
289+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
290+
with:
291+
name: dylibs
292+
path: ./build
293+
294+
- name: Insert dylibs
295+
run: |
296+
mv ./build/*amd64.dylib ./site/out/bin/coder-vpn-darwin-amd64.dylib
297+
mv ./build/*arm64.dylib ./site/out/bin/coder-vpn-darwin-arm64.dylib
298+
mv ./build/*arm64.h ./site/out/bin/coder-vpn-darwin-dylib.h
299+
297300
- name: Build binaries
298301
run: |
299302
set -euo pipefail
@@ -310,6 +313,7 @@ jobs:
310313
env:
311314
CODER_SIGN_WINDOWS: "1"
312315
CODER_SIGN_DARWIN: "1"
316+
CODER_WINDOWS_RESOURCES: "1"
313317
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
314318
AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt
315319
AC_APIKEY_ISSUER_ID: ${{ secrets.AC_APIKEY_ISSUER_ID }}

buildinfo/resources/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.syso

buildinfo/resources/resources.go

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// This package is used for embedding .syso resource files into the binary
2+
// during build and does not contain any code. During build, .syso files will be
3+
// dropped in this directory and then removed after the build completes.
4+
//
5+
// This package must be imported by all binaries for this to work.
6+
//
7+
// See build_go.sh for more details.
8+
package resources

cmd/coder/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
tea "github.com/charmbracelet/bubbletea"
99

1010
"github.com/coder/coder/v2/agent/agentexec"
11+
_ "github.com/coder/coder/v2/buildinfo/resources"
1112
"github.com/coder/coder/v2/cli"
1213
)
1314

enterprise/cmd/coder/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
tea "github.com/charmbracelet/bubbletea"
99

1010
"github.com/coder/coder/v2/agent/agentexec"
11+
_ "github.com/coder/coder/v2/buildinfo/resources"
1112
entcli "github.com/coder/coder/v2/enterprise/cli"
1213
)
1314

scripts/build_go.sh

+108-6
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,19 @@ source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
3636
version=""
3737
os="${GOOS:-linux}"
3838
arch="${GOARCH:-amd64}"
39+
output_path=""
3940
slim="${CODER_SLIM_BUILD:-0}"
41+
agpl="${CODER_BUILD_AGPL:-0}"
4042
sign_darwin="${CODER_SIGN_DARWIN:-0}"
4143
sign_windows="${CODER_SIGN_WINDOWS:-0}"
42-
bin_ident="com.coder.cli"
43-
output_path=""
44-
agpl="${CODER_BUILD_AGPL:-0}"
4544
boringcrypto=${CODER_BUILD_BORINGCRYPTO:-0}
46-
debug=0
4745
dylib=0
46+
windows_resources="${CODER_WINDOWS_RESOURCES:-0}"
47+
debug=0
48+
49+
bin_ident="com.coder.cli"
4850

49-
args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,boringcrypto,dylib,debug -- "$@")"
51+
args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,sign-windows,boringcrypto,dylib,windows-resources,debug -- "$@")"
5052
eval set -- "$args"
5153
while true; do
5254
case "$1" in
@@ -79,6 +81,10 @@ while true; do
7981
sign_darwin=1
8082
shift
8183
;;
84+
--sign-windows)
85+
sign_windows=1
86+
shift
87+
;;
8288
--boringcrypto)
8389
boringcrypto=1
8490
shift
@@ -87,6 +93,10 @@ while true; do
8793
dylib=1
8894
shift
8995
;;
96+
--windows-resources)
97+
windows_resources=1
98+
shift
99+
;;
90100
--debug)
91101
debug=1
92102
shift
@@ -115,11 +125,13 @@ if [[ "$sign_darwin" == 1 ]]; then
115125
dependencies rcodesign
116126
requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE
117127
fi
118-
119128
if [[ "$sign_windows" == 1 ]]; then
120129
dependencies java
121130
requiredenvs JSIGN_PATH EV_KEYSTORE EV_KEY EV_CERTIFICATE_PATH EV_TSA_URL GCLOUD_ACCESS_TOKEN
122131
fi
132+
if [[ "$windows_resources" == 1 ]]; then
133+
dependencies go-winres
134+
fi
123135

124136
ldflags=(
125137
-X "'github.com/coder/coder/v2/buildinfo.tag=$version'"
@@ -204,10 +216,100 @@ if [[ "$boringcrypto" == 1 ]]; then
204216
goexp="boringcrypto"
205217
fi
206218

219+
# On Windows, we use go-winres to embed the resources into the binary.
220+
if [[ "$windows_resources" == 1 ]] && [[ "$os" == "windows" ]]; then
221+
# Convert the version to a format that Windows understands.
222+
# Remove any trailing data after a "+" or "-".
223+
version_windows=$version
224+
version_windows="${version_windows%+*}"
225+
version_windows="${version_windows%-*}"
226+
# If there wasn't any extra data, add a .0 to the version. Otherwise, add
227+
# a .1 to the version to signify that this is not a release build so it can
228+
# be distinguished from a release build.
229+
non_release_build=0
230+
if [[ "$version_windows" == "$version" ]]; then
231+
version_windows+=".0"
232+
else
233+
version_windows+=".1"
234+
non_release_build=1
235+
fi
236+
237+
if [[ ! "$version_windows" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-1]$ ]]; then
238+
error "Computed invalid windows version format: $version_windows"
239+
fi
240+
241+
# File description changes based on slimness, AGPL status, and architecture.
242+
file_description="Coder"
243+
if [[ "$agpl" == 1 ]]; then
244+
file_description+=" AGPL"
245+
fi
246+
if [[ "$slim" == 1 ]]; then
247+
file_description+=" CLI"
248+
fi
249+
if [[ "$non_release_build" == 1 ]]; then
250+
file_description+=" (development build)"
251+
fi
252+
253+
# Because this writes to a file with the OS and arch in the filename, we
254+
# don't support concurrent builds for the same OS and arch (irregardless of
255+
# slimness or AGPL status).
256+
#
257+
# This is fine since we only embed resources during dogfood and release
258+
# builds, which use make (which will build all slim targets in parallel,
259+
# then all non-slim targets in parallel).
260+
expected_rsrc_file="./buildinfo/resources/resources_windows_${arch}.syso"
261+
if [[ -f "$expected_rsrc_file" ]]; then
262+
rm "$expected_rsrc_file"
263+
fi
264+
touch "$expected_rsrc_file"
265+
266+
pushd ./buildinfo/resources
267+
GOARCH="$arch" go-winres simply \
268+
--arch "$arch" \
269+
--out "resources" \
270+
--product-version "$version_windows" \
271+
--file-version "$version_windows" \
272+
--manifest "cli" \
273+
--file-description "$file_description" \
274+
--product-name "Coder" \
275+
--copyright "Copyright $(date +%Y) Coder Technologies Inc." \
276+
--original-filename "coder.exe" \
277+
--icon ../../scripts/win-installer/coder.ico
278+
popd
279+
280+
if [[ ! -f "$expected_rsrc_file" ]]; then
281+
error "Failed to generate $expected_rsrc_file"
282+
fi
283+
fi
284+
285+
set +e
207286
GOEXPERIMENT="$goexp" CGO_ENABLED="$cgo" GOOS="$os" GOARCH="$arch" GOARM="$arm_version" \
208287
go build \
209288
"${build_args[@]}" \
210289
"$cmd_path" 1>&2
290+
exit_code=$?
291+
set -e
292+
293+
# Clean up the resources file if it was generated.
294+
if [[ "$windows_resources" == 1 ]] && [[ "$os" == "windows" ]]; then
295+
rm "$expected_rsrc_file"
296+
fi
297+
298+
if [[ "$exit_code" != 0 ]]; then
299+
exit "$exit_code"
300+
fi
301+
302+
# If we did embed resources, verify that they were included.
303+
if [[ "$windows_resources" == 1 ]] && [[ "$os" == "windows" ]]; then
304+
winres_dir=$(mktemp -d)
305+
if ! go-winres extract --dir "$winres_dir" "$output_path" 1>&2; then
306+
rm -rf "$winres_dir"
307+
error "Compiled binary does not contain embedded resources"
308+
fi
309+
# If go-winres didn't return an error, it means it did find embedded
310+
# resources.
311+
rm -rf "$winres_dir"
312+
fi
211313

212314
if [[ "$sign_darwin" == 1 ]] && [[ "$os" == "darwin" ]]; then
213315
execrelative ./sign_darwin.sh "$output_path" "$bin_ident" 1>&2

0 commit comments

Comments
 (0)