18 Commits
v1.1 ... main

Author SHA1 Message Date
Solomon
21e6f8327e Add parallel processing of inputs
Support processing multiple inputs in parallel to reduce CI time
2026-01-06 14:41:27 +00:00
Gregory Szorc
a00d97f64d Upgrade estlin-plugin-jest 2026-01-04 17:18:40 -08:00
Gregory Szorc
e513b347e2 Update packages 2026-01-04 16:58:03 -08:00
Gregory Szorc
73aa91133e Upgrade prettier 2026-01-04 16:53:45 -08:00
Gregory Szorc
5590f32ee8 Regenerate bundle 2026-01-04 16:39:01 -08:00
dependabot[bot]
cb7589dd10 build(deps): bump super-linter/super-linter from 5 to 7 (#50)
Bumps [super-linter/super-linter](https://github.com/super-linter/super-linter) from 5 to 7.
- [Release notes](https://github.com/super-linter/super-linter/releases)
- [Changelog](https://github.com/super-linter/super-linter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/super-linter/super-linter/compare/v5...v7)

---
updated-dependencies:
- dependency-name: super-linter/super-linter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-04 16:20:30 -08:00
Gregory Szorc
7833348d60 Rename tool_cache -> toolCache
Per newer versions of JS Standard linter.
2024-11-11 19:10:45 -08:00
dependabot[bot]
f6c06bf15d build(deps): bump @actions/core from 1.10.1 to 1.11.1
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.10.1 to 1.11.1.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 18:56:40 -08:00
dependabot[bot]
7bfe322d33 build(deps-dev): bump @vercel/ncc from 0.38.1 to 0.38.2
Bumps [@vercel/ncc](https://github.com/vercel/ncc) from 0.38.1 to 0.38.2.
- [Release notes](https://github.com/vercel/ncc/releases)
- [Commits](https://github.com/vercel/ncc/compare/0.38.1...0.38.2)

---
updated-dependencies:
- dependency-name: "@vercel/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 18:54:47 -08:00
dependabot[bot]
f30a36a011 build(deps-dev): bump @babel/eslint-parser from 7.23.10 to 7.25.9 (#48)
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.23.10 to 7.25.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.25.9/eslint/babel-eslint-parser)

---
updated-dependencies:
- dependency-name: "@babel/eslint-parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 18:32:13 -08:00
dependabot[bot]
2f12e94a4f build(deps-dev): bump prettier from 3.2.5 to 3.3.3 (#45)
Bumps [prettier](https://github.com/prettier/prettier) from 3.2.5 to 3.3.3.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.2.5...3.3.3)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 18:31:43 -08:00
dependabot[bot]
ee15cda862 build(deps-dev): bump eslint-plugin-jest from 28.8.3 to 28.9.0 (#49)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 28.8.3 to 28.9.0.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v28.8.3...v28.9.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 18:31:24 -08:00
dependabot[bot]
0eaa356b2b build(deps-dev): bump eslint-plugin-jest from 27.6.3 to 28.8.3 (#41)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 27.6.3 to 28.8.3.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v27.6.3...v28.8.3)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-03 07:47:08 -08:00
Gregory Szorc
d39c8a8a72 Revert "build(deps): bump super-linter/super-linter from 5 to 7 (#38)" (#43)
This reverts commit 36cd284d61.
2024-11-03 07:44:19 -08:00
dependabot[bot]
de0535843d build(deps-dev): bump @babel/core from 7.23.9 to 7.26.0 (#40)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.23.9 to 7.26.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-03 07:40:57 -08:00
dependabot[bot]
37549037a5 build(deps-dev): bump @babel/preset-env from 7.23.9 to 7.26.0 (#42)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.23.9 to 7.26.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.0/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-03 07:40:42 -08:00
dependabot[bot]
579c4a847f build(deps-dev): bump eslint-plugin-github from 4.10.1 to 5.0.2 (#39)
Bumps [eslint-plugin-github](https://github.com/github/eslint-plugin-github) from 4.10.1 to 5.0.2.
- [Release notes](https://github.com/github/eslint-plugin-github/releases)
- [Commits](https://github.com/github/eslint-plugin-github/compare/v4.10.1...v5.0.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-github
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-03 07:40:14 -08:00
dependabot[bot]
36cd284d61 build(deps): bump super-linter/super-linter from 5 to 7 (#38)
Bumps [super-linter/super-linter](https://github.com/super-linter/super-linter) from 5 to 7.
- [Release notes](https://github.com/super-linter/super-linter/releases)
- [Changelog](https://github.com/super-linter/super-linter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/super-linter/super-linter/compare/v5...v7)

---
updated-dependencies:
- dependency-name: super-linter/super-linter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-03 07:39:52 -08:00
8 changed files with 4072 additions and 3912 deletions

View File

@@ -30,7 +30,7 @@ jobs:
- name: Lint Code Base
id: super-linter
uses: super-linter/super-linter/slim@v5
uses: super-linter/super-linter/slim@v7
env:
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -28,8 +28,12 @@ It is up to the caller to do something with the file/directory operated on.
See [action.yml](action.yml) for the set of inputs. The file should be
self-documenting.
The only output is `output_path`, which holds the filesystem path of the
signed/notarized/stapled entity.
The outputs are:
- `output_path`: filesystem path of the signed/notarized/stapled entity (or the
first path when multiple `input_path` values are provided).
- `output_paths`: newline-separated list of output paths when multiple
`input_path` values are provided.
## Examples
@@ -147,3 +151,21 @@ steps:
app_store_connect_api_issuer: 'abcdef-42-2411312...'
app_store_connect_api_key: 'DEADBEEF'
```
Notarize multiple signed assets in parallel.
```yaml
steps:
# Add steps here to materialize signed assets (.app/.zip/.dmg/etc).
- name: Notarize (parallel)
uses: BloopAI/apple-code-sign-action@v1
with:
input_path: |
MyApp.zip
MyOtherApp.zip
sign: false
notarize: true
notarize_concurrency: 2
app_store_connect_api_key_json_file: app_store_key.json
```

View File

@@ -26,6 +26,10 @@ inputs:
description: 'Whether to notarize'
default: 'false'
notarize_concurrency:
description: 'Max parallel notarization submissions when input_path is multi-line (0 = unlimited)'
default: '0'
# Attaches a pre-issued "notarization ticket" to an entity.
staple:
description: 'Whether to staple a notarization ticket'
@@ -113,7 +117,9 @@ inputs:
outputs:
output_path:
description: 'Path to signed/notarized/stapled entity'
description: 'Path to signed/notarized/stapled entity (first when multiple input_path values)'
output_paths:
description: 'Newline-separated list of output paths when multiple input_path values are provided'
runs:
using: node20

2284
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

20
dist/licenses.txt generated vendored
View File

@@ -166,10 +166,22 @@ uuid
MIT
The MIT License (MIT)
Copyright (c) 2010-2020 Robert Kieffer and other contributors
Copyright (c) 2010-2016 Robert Kieffer and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

5421
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -54,20 +54,20 @@
]
},
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/tool-cache": "^2.0.1"
},
"devDependencies": {
"@babel/core": "^7.23.9",
"@babel/eslint-parser": "^7.23.10",
"@babel/preset-env": "^7.23.9",
"@vercel/ncc": "^0.38.1",
"babel-preset-jest": "^29.6.3",
"@babel/core": "^7.26.0",
"@babel/eslint-parser": "^7.28.5",
"@babel/preset-env": "^7.28.5",
"@vercel/ncc": "^0.38.4",
"babel-preset-jest": "^30.2.0",
"eslint": "^8.56.0",
"eslint-plugin-github": "^4.10.1",
"eslint-plugin-jest": "^27.6.3",
"jest": "^29.7.0",
"prettier": "^3.2.5"
"eslint-plugin-github": "^5.0.2",
"eslint-plugin-jest": "^29.12.1",
"jest": "^30.2.0",
"prettier": "^3.5.0"
}
}

View File

@@ -1,8 +1,51 @@
const core = require('@actions/core')
const exec = require('@actions/exec')
const tool_cache = require('@actions/tool-cache')
const toolCache = require('@actions/tool-cache')
const os = require('os')
async function mapWithConcurrency(items, concurrency, fn) {
if (!Number.isInteger(concurrency) || concurrency < 1) {
throw new Error('concurrency must be a positive integer')
}
const results = new Array(items.length)
let nextIndex = 0
async function worker() {
for (let index = nextIndex++; index < items.length; index = nextIndex++) {
results[index] = await fn(items[index], index)
}
}
const workers = Array.from(
{ length: Math.min(concurrency, items.length) },
() => worker()
)
await Promise.all(workers)
return results
}
async function execRcodesign(rcodesign, args) {
let stdout = ''
let stderr = ''
const exitCode = await exec.exec(rcodesign, args, {
silent: true,
ignoreReturnCode: true,
listeners: {
stdout: data => {
stdout += data.toString()
},
stderr: data => {
stderr += data.toString()
}
}
})
return { exitCode, stdout, stderr }
}
async function getRcodesign(version) {
const platform = os.platform()
const arch = os.arch()
@@ -48,14 +91,14 @@ async function getRcodesign(version) {
core.info(`Downloading rcodesign from ${url}`)
const toolPath = await tool_cache.downloadTool(url)
const toolPath = await toolCache.downloadTool(url)
let destDir
if (url.endsWith('.tar.gz')) {
destDir = await tool_cache.extractTar(toolPath, 'rcodesign')
destDir = await toolCache.extractTar(toolPath, 'rcodesign')
} else {
destDir = await tool_cache.extractZip(toolPath, 'rcodesign')
destDir = await toolCache.extractZip(toolPath, 'rcodesign')
}
let exe = `${destDir}/${directory}/rcodesign`
@@ -68,10 +111,29 @@ async function getRcodesign(version) {
async function run() {
try {
const inputPath = core.getInput('input_path', { required: true })
const inputPathRaw = core.getInput('input_path', { required: true })
let inputPaths = core.getMultilineInput('input_path')
if (inputPaths.length === 1 && inputPaths[0].includes('\n')) {
inputPaths = inputPaths[0]
.split(/\r?\n/)
.map(line => line.trim())
.filter(Boolean)
}
if (inputPaths.length === 0) {
throw new Error('input_path is required')
}
const hasMultipleInputPaths = inputPaths.length > 1
const inputPath = inputPaths[0] || inputPathRaw.trim()
const outputPath = core.getInput('output_path')
const sign = core.getBooleanInput('sign')
const notarize = core.getBooleanInput('notarize')
const notarizeConcurrencyInput = core.getInput('notarize_concurrency')
const notarizeConcurrency = parseInt(notarizeConcurrencyInput || '0', 10)
if (Number.isNaN(notarizeConcurrency) || notarizeConcurrency < 0) {
throw new Error('notarize_concurrency must be a non-negative integer')
}
const staple = core.getBooleanInput('staple')
const configFiles = core.getMultilineInput('config_file')
const profile = core.getInput('profile')
@@ -96,9 +158,22 @@ async function run() {
const rcodesign = await getRcodesign(rcodesignVersion)
let signedPaths = inputPaths
let signedPath = inputPath
if (hasMultipleInputPaths && outputPath) {
throw new Error(
'output_path cannot be used with multiple input_path values'
)
}
if (sign) {
if (hasMultipleInputPaths) {
throw new Error(
'Multiple input_path values are not supported when sign=true'
)
}
const args = ['sign']
for (const path of configFiles) {
@@ -143,6 +218,7 @@ async function run() {
}
await exec.exec(rcodesign, args)
signedPaths = [signedPath]
}
let stapled = false
@@ -176,9 +252,64 @@ async function run() {
args.push('--wait')
}
args.push(signedPath)
const concurrency =
notarizeConcurrency > 0 ? notarizeConcurrency : signedPaths.length
await exec.exec(rcodesign, args)
core.info(`Submitting ${signedPaths.length} file(s) for notarization`)
const results = await mapWithConcurrency(
signedPaths,
concurrency,
async path => {
core.info(`Starting notarization: ${path}`)
const { exitCode, stdout, stderr } = await execRcodesign(rcodesign, [
...args,
path
])
if (exitCode === 0) {
return { path, ok: true, stdout, stderr }
}
return { path, ok: false, exitCode, stdout, stderr }
}
)
const failures = results.filter(r => !r.ok)
for (const result of results) {
core.startGroup(
result.ok
? `notary-submit: ${result.path}`
: `notary-submit failed: ${result.path}`
)
if (!result.ok) {
core.error(`exit code: ${result.exitCode}`)
}
if (result.stdout.trim()) {
if (result.ok) {
core.info(result.stdout.trim())
} else {
core.error(result.stdout.trim())
}
}
if (result.stderr.trim()) {
if (result.ok) {
core.info(result.stderr.trim())
} else {
core.error(result.stderr.trim())
}
}
core.endGroup()
}
if (failures.length > 0) {
throw new Error(
`Notarization failed for: ${failures.map(f => f.path).join(', ')}`
)
}
if (staple) {
stapled = true
@@ -192,12 +323,64 @@ async function run() {
args.push('--config-file', path)
}
args.push(signedPath)
const concurrency =
notarizeConcurrency > 0 ? notarizeConcurrency : signedPaths.length
await exec.exec(rcodesign, args)
const results = await mapWithConcurrency(
signedPaths,
concurrency,
async path => {
core.info(`Stapling notarization ticket: ${path}`)
const { exitCode, stdout, stderr } = await execRcodesign(rcodesign, [
...args,
path
])
if (exitCode === 0) {
return { path, ok: true, stdout, stderr }
}
return { path, ok: false, exitCode, stdout, stderr }
}
)
const failures = results.filter(r => !r.ok)
for (const result of results) {
core.startGroup(
result.ok ? `staple: ${result.path}` : `staple failed: ${result.path}`
)
if (!result.ok) {
core.error(`exit code: ${result.exitCode}`)
}
if (result.stdout.trim()) {
if (result.ok) {
core.info(result.stdout.trim())
} else {
core.error(result.stdout.trim())
}
}
if (result.stderr.trim()) {
if (result.ok) {
core.info(result.stderr.trim())
} else {
core.error(result.stderr.trim())
}
}
core.endGroup()
}
if (failures.length > 0) {
throw new Error(
`Stapling failed for: ${failures.map(f => f.path).join(', ')}`
)
}
}
core.setOutput('output_path', signedPath)
core.setOutput('output_path', signedPaths[0])
core.setOutput('output_paths', signedPaths.join('\n'))
} catch (error) {
core.setFailed(error.message)
}