Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 64b9f01

Browse filesBrowse files
update workflow files, delegate windows signing to custom script
1 parent aa9b10d commit 64b9f01
Copy full SHA for 64b9f01

File tree

4 files changed

+118
-37
lines changed
Filter options

4 files changed

+118
-37
lines changed

‎.github/workflows/build.yml

Copy file name to clipboardExpand all lines: .github/workflows/build.yml
+44-13Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,28 @@ env:
5555
- config:
5656
# Human identifier for the job.
5757
name: Windows
58-
runs-on: windows-2019
58+
runs-on: [self-hosted, windows-sign-pc]
5959
# The value is a string representing a JSON document.
6060
# Setting this to null causes the job to run directly in the runner machine instead of in a container.
6161
container: |
6262
null
6363
# Name of the secret that contains the certificate.
64-
certificate-secret: WINDOWS_SIGNING_CERTIFICATE_PFX
64+
certificate-secret: INSTALLER_CERT_WINDOWS_CER
6565
# Name of the secret that contains the certificate password.
66-
certificate-password-secret: WINDOWS_SIGNING_CERTIFICATE_PASSWORD
66+
certificate-password-secret: INSTALLER_CERT_WINDOWS_PASSWORD
6767
# File extension for the certificate.
6868
certificate-extension: pfx
69+
# Container for windows cert signing
70+
certificate-container: INSTALLER_CERT_WINDOWS_CONTAINER
6971
# Quoting on the value is required here to allow the same comparison expression syntax to be used for this
7072
# and the companion needs.select-targets.outputs.merge-channel-files property (output values always have string
7173
# type).
7274
mergeable-channel-file: 'false'
75+
# as this runs on a self hosted runner, we need to avoid building with the default working directory path,
76+
# otherwise paths in the build job will be too long for `light.exe`
77+
# we use the below as a Symbolic link (just changing the wd will break the checkout action)
78+
# this is a work around (see: https://github.com/actions/checkout/issues/197).
79+
working-directory: 'C:\a'
7380
artifacts:
7481
- path: '*Windows_64bit.exe'
7582
name: Windows_X86-64_interactive_installer
@@ -270,6 +277,14 @@ jobs:
270277
env:
271278
# Location of artifacts generated by build.
272279
BUILD_ARTIFACTS_PATH: electron-app/dist/build-artifacts
280+
# to skip passing signing credentials to electron-builder
281+
IS_WINDOWS_CONFIG: ${{ matrix.config.name == 'Windows' }}
282+
INSTALLER_CERT_WINDOWS_CER: "/tmp/cert.cer"
283+
# We are hardcoding the path for signtool because is not present on the windows PATH env var by default.
284+
# Keep in mind that this path could change when upgrading to a new runner version
285+
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0/x86/signtool.exe"
286+
WIN_CERT_PASSWORD: ${{ secrets.INSTALLER_CERT_WINDOWS_PASSWORD }}
287+
WIN_CERT_CONTAINER_NAME: ${{ secrets.INSTALLER_CERT_WINDOWS_CONTAINER }}
273288
strategy:
274289
matrix:
275290
config: ${{ fromJson(needs.select-targets.outputs.build-matrix) }}
@@ -283,6 +298,12 @@ jobs:
283298
timeout-minutes: 90
284299

285300
steps:
301+
- name: Symlink custom working directory
302+
shell: cmd
303+
if: runner.os == 'Windows' && matrix.config.working-directory
304+
run: |
305+
if not exist "${{ matrix.config.working-directory }}" mklink /d "${{ matrix.config.working-directory }}" "C:\actions-runner\_work\arduino-ide\arduino-ide"
306+
286307
- name: Checkout
287308
if: fromJSON(matrix.config.container) == null
288309
uses: actions/checkout@v4
@@ -293,42 +314,42 @@ jobs:
293314
uses: actions/checkout@v3
294315

295316
- name: Install Node.js
296-
if: fromJSON(matrix.config.container) == null
317+
if: fromJSON(matrix.config.container) == null && runner.os != 'Windows'
297318
uses: actions/setup-node@v4
298319
with:
299320
node-version: ${{ env.NODE_VERSION }}
300321
registry-url: 'https://registry.npmjs.org'
301322
cache: 'yarn'
302323

303324
- name: Install Python 3.x
304-
if: fromJSON(matrix.config.container) == null
325+
if: fromJSON(matrix.config.container) == null && runner.os != 'Windows'
305326
uses: actions/setup-python@v5
306327
with:
307328
python-version: '3.11.x'
308329

309330
- name: Install Go
310-
if: fromJSON(matrix.config.container) == null
331+
if: fromJSON(matrix.config.container) == null && runner.os != 'Windows'
311332
uses: actions/setup-go@v5
312333
with:
313334
go-version: ${{ env.GO_VERSION }}
314335

315336
- name: Install Go
316337
# actions/setup-go@v5 has dependency on a higher version of glibc than available in the Linux container.
317-
if: fromJSON(matrix.config.container) != null
338+
if: fromJSON(matrix.config.container) != null && runner.os != 'Windows'
318339
uses: actions/setup-go@v4
319340
with:
320341
go-version: ${{ env.GO_VERSION }}
321342

322343
- name: Install Taskfile
323-
if: fromJSON(matrix.config.container) == null
344+
if: fromJSON(matrix.config.container) == null && runner.os != 'Windows'
324345
uses: arduino/setup-task@v2
325346
with:
326347
repo-token: ${{ secrets.GITHUB_TOKEN }}
327348
version: 3.x
328349

329350
- name: Install Taskfile
330351
# actions/setup-task@v2 has dependency on a higher version of glibc than available in the Linux container.
331-
if: fromJSON(matrix.config.container) != null
352+
if: fromJSON(matrix.config.container) != null && runner.os != 'Windows'
332353
uses: arduino/setup-task@v1
333354
with:
334355
repo-token: ${{ secrets.GITHUB_TOKEN }}
@@ -350,9 +371,10 @@ jobs:
350371
CREATE_USERNAME: ${{ secrets.CREATE_USERNAME }}
351372
CREATE_PASSWORD: ${{ secrets.CREATE_PASSWORD }}
352373
CREATE_CLIENT_SECRET: ${{ secrets.CREATE_CLIENT_SECRET }}
374+
working-directory: ${{ runner.os == 'Windows' && matrix.config.working-directory || './' }}
353375
run: |
354376
# See: https://www.electron.build/code-signing
355-
if [ $CAN_SIGN = false ]; then
377+
if [ $CAN_SIGN = false ] || [ $IS_WINDOWS_CONFIG = true ]; then
356378
echo "Skipping the app signing: certificate not provided."
357379
else
358380
export CSC_LINK="${{ runner.temp }}/signing_certificate.${{ matrix.config.certificate-extension }}"
@@ -372,13 +394,14 @@ jobs:
372394
yarn --cwd electron-app rebuild
373395
yarn --cwd electron-app build
374396
yarn --cwd electron-app package
375-
397+
376398
# Both macOS jobs generate a "channel update info file" with same path and name. The second job to complete would
377399
# overwrite the file generated by the first in the workflow artifact.
378400
- name: Stage channel file for merge
379401
if: >
380402
needs.select-targets.outputs.merge-channel-files == 'true' &&
381403
matrix.config.mergeable-channel-file == 'true'
404+
working-directory: ${{ runner.os == 'Windows' && matrix.config.working-directory || './' }}
382405
run: |
383406
staged_channel_files_path="${{ runner.temp }}/staged-channel-files"
384407
mkdir "$staged_channel_files_path"
@@ -398,13 +421,21 @@ jobs:
398421
with:
399422
if-no-files-found: error
400423
name: ${{ env.STAGED_CHANNEL_FILES_ARTIFACT }}
401-
path: ${{ env.STAGED_CHANNEL_FILES_PATH }}
424+
path: ${{ runner.os == 'Windows' && matrix.config.working-directory && format('{0}/{1}', matrix.config.working-directory, env.STAGED_CHANNEL_FILES_PATH) || env.STAGED_CHANNEL_FILES_PATH }}
425+
402426

403427
- name: Upload [GitHub Actions]
404428
uses: actions/upload-artifact@v3
405429
with:
406430
name: ${{ env.JOB_TRANSFER_ARTIFACT }}
407-
path: ${{ env.BUILD_ARTIFACTS_PATH }}
431+
path: ${{ runner.os == 'Windows' && matrix.config.working-directory && format('{0}/{1}', matrix.config.working-directory, env.BUILD_ARTIFACTS_PATH) || env.BUILD_ARTIFACTS_PATH }}
432+
433+
- name: Manual Clean up for self-hosted runners
434+
if: runner.os == 'Windows' && matrix.config.working-directory
435+
shell: cmd
436+
run: |
437+
rmdir /s /q "${{ matrix.config.working-directory }}"
438+
rmdir /s /q "C:\actions-runner\_work\arduino-ide\arduino-ide"
408439
409440
merge-channel-files:
410441
needs:

‎.github/workflows/check-certificates.yml

Copy file name to clipboardExpand all lines: .github/workflows/check-certificates.yml
+42-23Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@ jobs:
7474
- identifier: macOS signing certificate # Text used to identify certificate in notifications.
7575
certificate-secret: APPLE_SIGNING_CERTIFICATE_P12 # Name of the secret that contains the certificate.
7676
password-secret: KEYCHAIN_PASSWORD # Name of the secret that contains the certificate password.
77+
type: pkcs12
7778
- identifier: Windows signing certificate
78-
certificate-secret: WINDOWS_SIGNING_CERTIFICATE_PFX
79-
password-secret: WINDOWS_SIGNING_CERTIFICATE_PASSWORD
79+
certificate-secret: INSTALLER_CERT_WINDOWS_CER
80+
# The password for the Windows certificate is not needed, because its not a container, but a single certificate.
81+
type: x509
8082

8183
steps:
8284
- name: Set certificate path environment variable
@@ -95,7 +97,7 @@ jobs:
9597
CERTIFICATE_PASSWORD: ${{ secrets[matrix.certificate.password-secret] }}
9698
run: |
9799
(
98-
openssl pkcs12 \
100+
openssl ${{ matrix.certificate.type }} \
99101
-in "${{ env.CERTIFICATE_PATH }}" \
100102
-legacy \
101103
-noout \
@@ -122,26 +124,43 @@ jobs:
122124
CERTIFICATE_PASSWORD: ${{ secrets[matrix.certificate.password-secret] }}
123125
id: get-days-before-expiration
124126
run: |
125-
EXPIRATION_DATE="$(
126-
(
127-
openssl pkcs12 \
128-
-in "${{ env.CERTIFICATE_PATH }}" \
129-
-clcerts \
130-
-legacy \
131-
-nodes \
132-
-passin env:CERTIFICATE_PASSWORD
133-
) | (
134-
openssl x509 \
135-
-noout \
136-
-enddate
137-
) | (
138-
grep \
139-
--max-count=1 \
140-
--only-matching \
141-
--perl-regexp \
142-
'notAfter=(\K.*)'
143-
)
144-
)"
127+
if [[ ${{ matrix.certificate.type }} == "pkcs12" ]]; then
128+
EXPIRATION_DATE="$(
129+
(
130+
openssl pkcs12 \
131+
-in "${{ env.CERTIFICATE_PATH }}" \
132+
-clcerts \
133+
-legacy \
134+
-nodes \
135+
-passin env:CERTIFICATE_PASSWORD
136+
) | (
137+
openssl x509 \
138+
-noout \
139+
-enddate
140+
) | (
141+
grep \
142+
--max-count=1 \
143+
--only-matching \
144+
--perl-regexp \
145+
'notAfter=(\K.*)'
146+
)
147+
)"
148+
elif [[ ${{ matrix.certificate.type }} == "x509" ]]; then
149+
EXPIRATION_DATE="$(
150+
(
151+
openssl x509 \
152+
-in ${{ env.CERTIFICATE_PATH }} \
153+
-noout \
154+
-enddate
155+
) | (
156+
grep \
157+
--max-count=1 \
158+
--only-matching \
159+
--perl-regexp \
160+
'notAfter=(\K.*)'
161+
)
162+
)"
163+
fi
145164
146165
DAYS_BEFORE_EXPIRATION="$((($(date --utc --date="$EXPIRATION_DATE" +%s) - $(date --utc +%s)) / 60 / 60 / 24))"
147166

‎electron-app/package.json

Copy file name to clipboardExpand all lines: electron-app/package.json
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@
133133
"msi",
134134
"nsis",
135135
"zip"
136-
]
136+
],
137+
"sign": "./scripts/windowsCustomSign.js"
137138
},
138139
"mac": {
139140
"darkModeSupport": true,
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const childProcess = require('child_process');
2+
3+
exports.default = async function (configuration) {
4+
if (!process.env.GITHUB_ACTIONS) {
5+
return;
6+
}
7+
8+
const SIGNTOOL_PATH = process.env.SIGNTOOL_PATH;
9+
const INSTALLER_CERT_WINDOWS_CER = process.env.INSTALLER_CERT_WINDOWS_CER;
10+
const CERT_PASSWORD = process.env.WIN_CERT_PASSWORD;
11+
const CONTAINER_NAME = process.env.WIN_CERT_CONTAINER_NAME;
12+
const filePath = configuration.path;
13+
14+
if (
15+
SIGNTOOL_PATH &&
16+
INSTALLER_CERT_WINDOWS_CER &&
17+
CERT_PASSWORD &&
18+
CONTAINER_NAME
19+
) {
20+
childProcess.execSync(
21+
`"${SIGNTOOL_PATH}" sign -d "Arduino IDE" -f "${INSTALLER_CERT_WINDOWS_CER}" -csp "eToken Base Cryptographic Provider" -k "[{{${CERT_PASSWORD}}}]=${CONTAINER_NAME}" -fd sha256 -tr http://timestamp.digicert.com -td SHA256 -v "${filePath}"`,
22+
{ stdio: 'inherit' }
23+
);
24+
} else {
25+
console.warn(
26+
`Custom windows signing was no performed one of the following variables was not provided: SIGNTOOL_PATH (${SIGNTOOL_PATH}), INSTALLER_CERT_WINDOWS_CERT (${INSTALLER_CERT_WINDOWS_CER}), CERT_PASSWORD (${CERT_PASSWORD}), CONTAINER_NAME (${CONTAINER_NAME})`
27+
);
28+
process.exit(1);
29+
}
30+
};

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.