mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: include winres metadata in Windows binaries (#16706)
Adds information like product/file version, description, product name and copyright to compiled Windows binaries in dogfood and release builds. Also adds an icon to the executable. This is necessary for Coder Desktop to be able to check the version on binaries. ### Before:   ### After:    Closes https://github.com/coder/coder/issues/16693
This commit is contained in:
@@ -1021,7 +1021,10 @@ jobs:
|
||||
if: github.ref == 'refs/heads/main' && 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:
|
||||
packages: write # Needed to push images to ghcr.io
|
||||
# Necessary to push docker images to ghcr.io.
|
||||
packages: write
|
||||
# Necessary for GCP authentication (https://github.com/google-github-actions/setup-gcloud#usage)
|
||||
id-token: write
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: "enabled"
|
||||
outputs:
|
||||
@@ -1050,12 +1053,44 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: ./.github/actions/setup-go
|
||||
|
||||
# Necessary for signing Windows binaries.
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: "11.0"
|
||||
|
||||
- name: Install go-winres
|
||||
run: go install github.com/tc-hib/go-winres@d743268d7ea168077ddd443c4240562d4f5e8c3e # v0.3.3
|
||||
|
||||
- name: Install nfpm
|
||||
run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.35.1
|
||||
|
||||
- name: Install zstd
|
||||
run: sudo apt-get install -y zstd
|
||||
|
||||
- name: Setup Windows EV Signing Certificate
|
||||
run: |
|
||||
set -euo pipefail
|
||||
touch /tmp/ev_cert.pem
|
||||
chmod 600 /tmp/ev_cert.pem
|
||||
echo "$EV_SIGNING_CERT" > /tmp/ev_cert.pem
|
||||
wget https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar -O /tmp/jsign-6.0.jar
|
||||
env:
|
||||
EV_SIGNING_CERT: ${{ secrets.EV_SIGNING_CERT }}
|
||||
|
||||
# Setup GCloud for signing Windows binaries.
|
||||
- name: Authenticate to Google Cloud
|
||||
id: gcloud_auth
|
||||
uses: google-github-actions/auth@71f986410dfbc7added4569d411d040a91dc6935 # v2.1.8
|
||||
with:
|
||||
workload_identity_provider: ${{ secrets.GCP_CODE_SIGNING_WORKLOAD_ID_PROVIDER }}
|
||||
service_account: ${{ secrets.GCP_CODE_SIGNING_SERVICE_ACCOUNT }}
|
||||
token_format: "access_token"
|
||||
|
||||
- name: Setup GCloud SDK
|
||||
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
|
||||
|
||||
- name: Download dylibs
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
@@ -1082,6 +1117,18 @@ jobs:
|
||||
build/coder_linux_{amd64,arm64,armv7} \
|
||||
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).
|
||||
CODER_SIGN_WINDOWS: "1"
|
||||
CODER_WINDOWS_RESOURCES: "1"
|
||||
EV_KEY: ${{ secrets.EV_KEY }}
|
||||
EV_KEYSTORE: ${{ secrets.EV_KEYSTORE }}
|
||||
EV_TSA_URL: ${{ secrets.EV_TSA_URL }}
|
||||
EV_CERTIFICATE_PATH: /tmp/ev_cert.pem
|
||||
GCLOUD_ACCESS_TOKEN: ${{ steps.gcloud_auth.outputs.access_token }}
|
||||
JSIGN_PATH: /tmp/jsign-6.0.jar
|
||||
|
||||
- name: Build Linux Docker images
|
||||
id: build-docker
|
||||
@@ -1183,10 +1230,10 @@ jobs:
|
||||
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
|
||||
|
||||
- name: Set up Flux CLI
|
||||
uses: fluxcd/flux2/action@af67405ee43a6cd66e0b73f4b3802e8583f9d961 # v2.5.0
|
||||
uses: fluxcd/flux2/action@8d5f40dca5aa5d3c0fc3414457dda15a0ac92fa4 # v2.5.1
|
||||
with:
|
||||
# Keep this and the github action up to date with the version of flux installed in dogfood cluster
|
||||
version: "2.2.1"
|
||||
version: "2.5.1"
|
||||
|
||||
- name: Get Cluster Credentials
|
||||
uses: google-github-actions/get-gke-credentials@7a108e64ed8546fe38316b4086e91da13f4785e1 # v2.3.1
|
||||
|
||||
@@ -223,21 +223,12 @@ jobs:
|
||||
distribution: "zulu"
|
||||
java-version: "11.0"
|
||||
|
||||
- name: Install go-winres
|
||||
run: go install github.com/tc-hib/go-winres@d743268d7ea168077ddd443c4240562d4f5e8c3e # v0.3.3
|
||||
|
||||
- name: Install nsis and zstd
|
||||
run: sudo apt-get install -y nsis zstd
|
||||
|
||||
- name: Download dylibs
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
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: Install nfpm
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -294,6 +285,18 @@ jobs:
|
||||
- name: Setup GCloud SDK
|
||||
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
|
||||
|
||||
- name: Download dylibs
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
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
|
||||
@@ -310,6 +313,7 @@ jobs:
|
||||
env:
|
||||
CODER_SIGN_WINDOWS: "1"
|
||||
CODER_SIGN_DARWIN: "1"
|
||||
CODER_WINDOWS_RESOURCES: "1"
|
||||
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
|
||||
AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt
|
||||
AC_APIKEY_ISSUER_ID: ${{ secrets.AC_APIKEY_ISSUER_ID }}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
*.syso
|
||||
@@ -0,0 +1,8 @@
|
||||
// This package is used for embedding .syso resource files into the binary
|
||||
// during build and does not contain any code. During build, .syso files will be
|
||||
// dropped in this directory and then removed after the build completes.
|
||||
//
|
||||
// This package must be imported by all binaries for this to work.
|
||||
//
|
||||
// See build_go.sh for more details.
|
||||
package resources
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
|
||||
"github.com/coder/coder/v2/agent/agentexec"
|
||||
_ "github.com/coder/coder/v2/buildinfo/resources"
|
||||
"github.com/coder/coder/v2/cli"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
|
||||
"github.com/coder/coder/v2/agent/agentexec"
|
||||
_ "github.com/coder/coder/v2/buildinfo/resources"
|
||||
entcli "github.com/coder/coder/v2/enterprise/cli"
|
||||
)
|
||||
|
||||
|
||||
+108
-6
@@ -36,17 +36,19 @@ source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
||||
version=""
|
||||
os="${GOOS:-linux}"
|
||||
arch="${GOARCH:-amd64}"
|
||||
output_path=""
|
||||
slim="${CODER_SLIM_BUILD:-0}"
|
||||
agpl="${CODER_BUILD_AGPL:-0}"
|
||||
sign_darwin="${CODER_SIGN_DARWIN:-0}"
|
||||
sign_windows="${CODER_SIGN_WINDOWS:-0}"
|
||||
bin_ident="com.coder.cli"
|
||||
output_path=""
|
||||
agpl="${CODER_BUILD_AGPL:-0}"
|
||||
boringcrypto=${CODER_BUILD_BORINGCRYPTO:-0}
|
||||
debug=0
|
||||
dylib=0
|
||||
windows_resources="${CODER_WINDOWS_RESOURCES:-0}"
|
||||
debug=0
|
||||
|
||||
args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,boringcrypto,dylib,debug -- "$@")"
|
||||
bin_ident="com.coder.cli"
|
||||
|
||||
args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,sign-windows,boringcrypto,dylib,windows-resources,debug -- "$@")"
|
||||
eval set -- "$args"
|
||||
while true; do
|
||||
case "$1" in
|
||||
@@ -79,6 +81,10 @@ while true; do
|
||||
sign_darwin=1
|
||||
shift
|
||||
;;
|
||||
--sign-windows)
|
||||
sign_windows=1
|
||||
shift
|
||||
;;
|
||||
--boringcrypto)
|
||||
boringcrypto=1
|
||||
shift
|
||||
@@ -87,6 +93,10 @@ while true; do
|
||||
dylib=1
|
||||
shift
|
||||
;;
|
||||
--windows-resources)
|
||||
windows_resources=1
|
||||
shift
|
||||
;;
|
||||
--debug)
|
||||
debug=1
|
||||
shift
|
||||
@@ -115,11 +125,13 @@ if [[ "$sign_darwin" == 1 ]]; then
|
||||
dependencies rcodesign
|
||||
requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE
|
||||
fi
|
||||
|
||||
if [[ "$sign_windows" == 1 ]]; then
|
||||
dependencies java
|
||||
requiredenvs JSIGN_PATH EV_KEYSTORE EV_KEY EV_CERTIFICATE_PATH EV_TSA_URL GCLOUD_ACCESS_TOKEN
|
||||
fi
|
||||
if [[ "$windows_resources" == 1 ]]; then
|
||||
dependencies go-winres
|
||||
fi
|
||||
|
||||
ldflags=(
|
||||
-X "'github.com/coder/coder/v2/buildinfo.tag=$version'"
|
||||
@@ -204,10 +216,100 @@ if [[ "$boringcrypto" == 1 ]]; then
|
||||
goexp="boringcrypto"
|
||||
fi
|
||||
|
||||
# On Windows, we use go-winres to embed the resources into the binary.
|
||||
if [[ "$windows_resources" == 1 ]] && [[ "$os" == "windows" ]]; then
|
||||
# Convert the version to a format that Windows understands.
|
||||
# Remove any trailing data after a "+" or "-".
|
||||
version_windows=$version
|
||||
version_windows="${version_windows%+*}"
|
||||
version_windows="${version_windows%-*}"
|
||||
# If there wasn't any extra data, add a .0 to the version. Otherwise, add
|
||||
# a .1 to the version to signify that this is not a release build so it can
|
||||
# be distinguished from a release build.
|
||||
non_release_build=0
|
||||
if [[ "$version_windows" == "$version" ]]; then
|
||||
version_windows+=".0"
|
||||
else
|
||||
version_windows+=".1"
|
||||
non_release_build=1
|
||||
fi
|
||||
|
||||
if [[ ! "$version_windows" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-1]$ ]]; then
|
||||
error "Computed invalid windows version format: $version_windows"
|
||||
fi
|
||||
|
||||
# File description changes based on slimness, AGPL status, and architecture.
|
||||
file_description="Coder"
|
||||
if [[ "$agpl" == 1 ]]; then
|
||||
file_description+=" AGPL"
|
||||
fi
|
||||
if [[ "$slim" == 1 ]]; then
|
||||
file_description+=" CLI"
|
||||
fi
|
||||
if [[ "$non_release_build" == 1 ]]; then
|
||||
file_description+=" (development build)"
|
||||
fi
|
||||
|
||||
# Because this writes to a file with the OS and arch in the filename, we
|
||||
# don't support concurrent builds for the same OS and arch (irregardless of
|
||||
# slimness or AGPL status).
|
||||
#
|
||||
# This is fine since we only embed resources during dogfood and release
|
||||
# builds, which use make (which will build all slim targets in parallel,
|
||||
# then all non-slim targets in parallel).
|
||||
expected_rsrc_file="./buildinfo/resources/resources_windows_${arch}.syso"
|
||||
if [[ -f "$expected_rsrc_file" ]]; then
|
||||
rm "$expected_rsrc_file"
|
||||
fi
|
||||
touch "$expected_rsrc_file"
|
||||
|
||||
pushd ./buildinfo/resources
|
||||
GOARCH="$arch" go-winres simply \
|
||||
--arch "$arch" \
|
||||
--out "resources" \
|
||||
--product-version "$version_windows" \
|
||||
--file-version "$version_windows" \
|
||||
--manifest "cli" \
|
||||
--file-description "$file_description" \
|
||||
--product-name "Coder" \
|
||||
--copyright "Copyright $(date +%Y) Coder Technologies Inc." \
|
||||
--original-filename "coder.exe" \
|
||||
--icon ../../scripts/win-installer/coder.ico
|
||||
popd
|
||||
|
||||
if [[ ! -f "$expected_rsrc_file" ]]; then
|
||||
error "Failed to generate $expected_rsrc_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
set +e
|
||||
GOEXPERIMENT="$goexp" CGO_ENABLED="$cgo" GOOS="$os" GOARCH="$arch" GOARM="$arm_version" \
|
||||
go build \
|
||||
"${build_args[@]}" \
|
||||
"$cmd_path" 1>&2
|
||||
exit_code=$?
|
||||
set -e
|
||||
|
||||
# Clean up the resources file if it was generated.
|
||||
if [[ "$windows_resources" == 1 ]] && [[ "$os" == "windows" ]]; then
|
||||
rm "$expected_rsrc_file"
|
||||
fi
|
||||
|
||||
if [[ "$exit_code" != 0 ]]; then
|
||||
exit "$exit_code"
|
||||
fi
|
||||
|
||||
# If we did embed resources, verify that they were included.
|
||||
if [[ "$windows_resources" == 1 ]] && [[ "$os" == "windows" ]]; then
|
||||
winres_dir=$(mktemp -d)
|
||||
if ! go-winres extract --dir "$winres_dir" "$output_path" 1>&2; then
|
||||
rm -rf "$winres_dir"
|
||||
error "Compiled binary does not contain embedded resources"
|
||||
fi
|
||||
# If go-winres didn't return an error, it means it did find embedded
|
||||
# resources.
|
||||
rm -rf "$winres_dir"
|
||||
fi
|
||||
|
||||
if [[ "$sign_darwin" == 1 ]] && [[ "$os" == "darwin" ]]; then
|
||||
execrelative ./sign_darwin.sh "$output_path" "$bin_ident" 1>&2
|
||||
|
||||
Reference in New Issue
Block a user