Skip to content

Commit e329fff

Browse files
authored
ci: distribute 3rd-party integrations via Craft (#8633)
* ci: distribute 3rd-party integrations via Craft Add Craft `commit-on-git-repository` targets so each 3rd-party integration package is pushed to its own repo on release: - SentrySwiftLog → sentry-apple-swift-log - SentrySwiftyBeaver → sentry-apple-swiftybeaver - SentryPulse → sentry-apple-pulse - SentryCocoaLumberjack → sentry-apple-cocoalumberjack New archive script creates .tgz bundles with sources, tests, README, .gitignore, and LICENSE.md from the repo root. Extract shared staging/tar helpers into ci-utils.sh and migrate both archive scripts to use them. * fix: create output directory before writing archives * fix: resolve archive path to absolute before cd * fix: prevent tar option injection in archive helper Use NUL-delimited pipeline and -- end-of-options separator so filenames starting with - cannot be interpreted as tar flags. * ci: add ci-utils.sh to archive workflow file filters Changes to the shared archive helper now trigger both the apple-binaries and 3rd-party-integrations archive workflows.
1 parent 0ba566f commit e329fff

7 files changed

Lines changed: 269 additions & 14 deletions

File tree

.craft.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,26 @@ targets:
99
repositoryUrl: https://github.com/getsentry/sentry-apple-binaries
1010
branch: main
1111
createTag: true
12+
- name: commit-on-git-repository
13+
archive: /^sentry-apple-swift-log\.tgz$/
14+
repositoryUrl: https://github.com/getsentry/sentry-apple-swift-log
15+
branch: main
16+
createTag: true
17+
- name: commit-on-git-repository
18+
archive: /^sentry-apple-swiftybeaver\.tgz$/
19+
repositoryUrl: https://github.com/getsentry/sentry-apple-swiftybeaver
20+
branch: main
21+
createTag: true
22+
- name: commit-on-git-repository
23+
archive: /^sentry-apple-pulse\.tgz$/
24+
repositoryUrl: https://github.com/getsentry/sentry-apple-pulse
25+
branch: main
26+
createTag: true
27+
- name: commit-on-git-repository
28+
archive: /^sentry-apple-cocoalumberjack\.tgz$/
29+
repositoryUrl: https://github.com/getsentry/sentry-apple-cocoalumberjack
30+
branch: main
31+
createTag: true
1232
# The canonical name 'cocoapods:sentry-cocoa' is a historical artifact from when
1333
# the SDK was distributed via CocoaPods. Changing it requires manual surgery in
1434
# the sentry-release-registry repo, so we keep it as-is.

.github/file-filters.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,16 @@ run_apple_binaries_archive_for_prs: &run_apple_binaries_archive_for_prs
447447
- ".github/workflows/apple-binaries-archive.yml"
448448
- ".github/file-filters.yml"
449449
- "scripts/create-apple-binaries-archive.sh"
450+
- "scripts/ci-utils.sh"
450451
- "distribution/**"
451452

453+
run_3rd_party_integrations_archive_for_prs: &run_3rd_party_integrations_archive_for_prs
454+
- ".github/workflows/3rd-party-integrations-archive.yml"
455+
- ".github/file-filters.yml"
456+
- "scripts/create-3rd-party-integration-archive.sh"
457+
- "scripts/ci-utils.sh"
458+
- "3rd-party-integrations/**"
459+
452460
run_ui_tests_for_prs: &run_ui_tests_for_prs
453461
- "Sources/**"
454462
- "Tests/**"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: Test 3rd-Party Integrations Archive
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
pull_request:
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
13+
14+
jobs:
15+
files-changed:
16+
name: Detect File Changes
17+
runs-on: ubuntu-latest
18+
outputs:
19+
run_for_prs: ${{ steps.changes.outputs.run_3rd_party_integrations_archive_for_prs }}
20+
steps:
21+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22+
- name: Get changed files
23+
id: changes
24+
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
25+
with:
26+
token: ${{ github.token }}
27+
filters: .github/file-filters.yml
28+
29+
test-3rd-party-integrations-archive:
30+
if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_for_prs == 'true'
31+
needs: files-changed
32+
name: Test 3rd-Party Integrations Archive
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
36+
37+
- name: Create archives
38+
run: |
39+
./scripts/create-3rd-party-integration-archive.sh \
40+
--all \
41+
--output-dir /tmp/3rd-party-archives
42+
43+
- name: Verify archives
44+
run: |
45+
INTEGRATIONS=(
46+
"sentry-apple-swift-log:SentryLogHandler.swift:SentryLogHandlerTests.swift"
47+
"sentry-apple-swiftybeaver:SentryDestination.swift:SentryDestinationTests.swift"
48+
"sentry-apple-pulse:SentryPulse.swift:SentryPulseTests.swift"
49+
"sentry-apple-cocoalumberjack:SentryCocoaLumberjackLogger.swift:SentryCocoaLumberjackLoggerTests.swift"
50+
)
51+
52+
for entry in "${INTEGRATIONS[@]}"; do
53+
IFS=':' read -r archive_name source_file test_file <<< "$entry"
54+
archive="/tmp/3rd-party-archives/${archive_name}.tgz"
55+
verify_dir="/tmp/3rd-party-verify/${archive_name}"
56+
57+
echo "=== Verifying ${archive_name} ==="
58+
59+
test -f "$archive" || { echo "Archive not found: $archive"; exit 1; }
60+
61+
mkdir -p "$verify_dir"
62+
tar -xzf "$archive" -C "$verify_dir"
63+
64+
# Verify expected files exist
65+
test -f "$verify_dir/Package.swift"
66+
test -f "$verify_dir/.gitignore"
67+
test -f "$verify_dir/README.md"
68+
test -f "$verify_dir/LICENSE.md"
69+
test -f "$verify_dir/Sources/$source_file"
70+
test -f "$verify_dir/Tests/$test_file"
71+
72+
echo "${archive_name} verified successfully"
73+
done
74+
75+
echo "All 3rd-party integration archives verified successfully"
76+
77+
third-party-integrations-archive-required-check:
78+
needs:
79+
[
80+
files-changed,
81+
test-3rd-party-integrations-archive,
82+
]
83+
name: Test 3rd-Party Integrations Archive - Required Check
84+
if: always()
85+
runs-on: ubuntu-latest
86+
steps:
87+
- name: Check for failures
88+
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
89+
run: |
90+
echo "3rd-party integrations archive test failed." && exit 1

.github/workflows/release.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,13 @@ jobs:
516516
--xcframework-dir XCFrameworkBuildPath \
517517
--output-dir XCFrameworkBuildPath
518518
519+
- name: Create 3rd-party integration archives
520+
if: ${{ github.event_name == 'workflow_dispatch' }}
521+
run: |
522+
./scripts/create-3rd-party-integration-archive.sh \
523+
--all \
524+
--output-dir XCFrameworkBuildPath
525+
519526
- name: Archive XCFrameworks for Craft
520527
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
521528
with:

scripts/ci-utils.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,29 @@ append_summary() {
213213
echo "[summary] ${content}"
214214
fi
215215
}
216+
217+
# Create a .tgz archive from a staging directory.
218+
#
219+
# Usage:
220+
# staging_dir=$(create_staging_dir)
221+
# # ... populate $staging_dir ...
222+
# create_tgz_from_staging "$staging_dir" "/path/to/output.tgz"
223+
#
224+
# The staging directory is removed after the archive is created.
225+
create_staging_dir() {
226+
mktemp -d
227+
}
228+
229+
create_tgz_from_staging() {
230+
local staging_dir="$1"
231+
local archive_path
232+
archive_path="$(cd "$(dirname "$2")" && pwd)/$(basename "$2")"
233+
234+
(cd "$staging_dir" && find . -type f -print0 | sed -z 's|^\./||' | sort -z | xargs -0 tar -czf "$archive_path" --)
235+
236+
rm -rf "$staging_dir"
237+
238+
log_info "Created $archive_path"
239+
log_info "Contents:"
240+
tar -tzf "$archive_path"
241+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
# shellcheck source=./ci-utils.sh disable=SC1091
6+
source "$SCRIPT_DIR/ci-utils.sh"
7+
8+
OUTPUT_DIR=""
9+
INTEGRATION=""
10+
ALL=false
11+
12+
INTEGRATIONS_DIR="3rd-party-integrations"
13+
14+
ALL_DIR_NAMES="SentrySwiftLog SentrySwiftyBeaver SentryPulse SentryCocoaLumberjack"
15+
16+
archive_name_for() {
17+
case "$1" in
18+
SentrySwiftLog) echo "sentry-apple-swift-log" ;;
19+
SentrySwiftyBeaver) echo "sentry-apple-swiftybeaver" ;;
20+
SentryPulse) echo "sentry-apple-pulse" ;;
21+
SentryCocoaLumberjack) echo "sentry-apple-cocoalumberjack" ;;
22+
*) echo "" ;;
23+
esac
24+
}
25+
26+
usage() {
27+
cat <<EOF
28+
Usage: $(basename "$0") [options]
29+
30+
Create .tgz archives for 3rd-party integration distribution repos.
31+
Copies sources, tests, README, .gitignore, and LICENSE.md.
32+
33+
OPTIONS:
34+
--integration <name> Directory name under $INTEGRATIONS_DIR
35+
(e.g. SentrySwiftLog)
36+
--all Archive all integrations
37+
--output-dir <path> Directory to write archives to (default: repo root)
38+
-h, --help Show this help message
39+
40+
EXAMPLES:
41+
$(basename "$0") --all
42+
$(basename "$0") --integration SentrySwiftLog
43+
$(basename "$0") --all --output-dir XCFrameworkBuildPath
44+
45+
EOF
46+
exit 1
47+
}
48+
49+
while [[ $# -gt 0 ]]; do
50+
case $1 in
51+
--integration) INTEGRATION="$2"; shift 2 ;;
52+
--all) ALL=true; shift ;;
53+
--output-dir) OUTPUT_DIR="$2"; shift 2 ;;
54+
-h|--help) usage ;;
55+
*) log_error "Unknown option: $1"; usage ;;
56+
esac
57+
done
58+
59+
if [ "$ALL" = false ] && [ -z "$INTEGRATION" ]; then
60+
log_error "Either --all or --integration <name> is required"
61+
usage
62+
fi
63+
64+
REPO_ROOT="$SCRIPT_DIR/.."
65+
66+
if [ -z "$OUTPUT_DIR" ]; then
67+
OUTPUT_DIR="$REPO_ROOT"
68+
fi
69+
70+
mkdir -p "$OUTPUT_DIR"
71+
72+
create_archive() {
73+
local dir_name="$1"
74+
local archive_name
75+
archive_name=$(archive_name_for "$dir_name")
76+
local src_dir="$REPO_ROOT/$INTEGRATIONS_DIR/$dir_name"
77+
78+
if [ -z "$archive_name" ]; then
79+
log_error "Unknown integration: $dir_name"
80+
exit 1
81+
fi
82+
83+
if [ ! -d "$src_dir" ]; then
84+
log_error "Directory not found: $src_dir"
85+
exit 1
86+
fi
87+
88+
local archive_file="$archive_name.tgz"
89+
local archive_path="$OUTPUT_DIR/$archive_file"
90+
91+
begin_group "Create $archive_file"
92+
93+
local staging_dir
94+
staging_dir=$(create_staging_dir)
95+
96+
cp "$src_dir/Package.swift" "$staging_dir/Package.swift"
97+
cp "$src_dir/.gitignore" "$staging_dir/.gitignore"
98+
cp "$src_dir/README.md" "$staging_dir/README.md"
99+
cp "$REPO_ROOT/LICENSE.md" "$staging_dir/LICENSE.md"
100+
101+
cp -R "$src_dir/Sources" "$staging_dir/Sources"
102+
cp -R "$src_dir/Tests" "$staging_dir/Tests"
103+
104+
create_tgz_from_staging "$staging_dir" "$archive_path"
105+
106+
end_group
107+
}
108+
109+
if [ "$ALL" = true ]; then
110+
for dir_name in $ALL_DIR_NAMES; do
111+
create_archive "$dir_name"
112+
done
113+
else
114+
create_archive "$INTEGRATION"
115+
fi

scripts/create-apple-binaries-archive.sh

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ ARCHIVE_PATH="$OUTPUT_DIR/$ARCHIVE_NAME"
7070

7171
begin_group "Create $ARCHIVE_NAME"
7272

73-
STAGING_DIR=$(mktemp -d)
74-
trap 'rm -rf "$STAGING_DIR"' EXIT
73+
STAGING_DIR=$(create_staging_dir)
7574

7675
cp "$DIST_DIR/Package.swift" "$STAGING_DIR/Package.swift"
7776
cp "$DIST_DIR/.gitignore" "$STAGING_DIR/.gitignore"
@@ -83,6 +82,7 @@ cp "$DIST_DIR/Sources/SentryCppHelper/SentryCppHelper.swift" "$STAGING_DIR/Sourc
8382
log_info "Preparing CHANGELOG.md for version $VERSION"
8483
cp "$REPO_ROOT/CHANGELOG.md" "$STAGING_DIR/CHANGELOG.md"
8584
sed -i.bak "s/^## Unreleased$/## ${VERSION}/" "$STAGING_DIR/CHANGELOG.md"
85+
rm -f "$STAGING_DIR/CHANGELOG.md.bak"
8686

8787
log_info "Stamping version $VERSION into Package.swift"
8888
sed -i.bak "s|releases/download/[^/]*/|releases/download/${VERSION}/|g" "$STAGING_DIR/Package.swift"
@@ -103,17 +103,6 @@ for entry in "${ZIPS_AND_MARKERS[@]}"; do
103103
log_info " ${marker}: ${checksum}"
104104
done
105105

106-
tar -czf "$ARCHIVE_PATH" \
107-
-C "$STAGING_DIR" \
108-
Package.swift \
109-
Sources/SentryCppHelper/SentryCppHelper.swift \
110-
CHANGELOG.md \
111-
README.md \
112-
LICENSE.md \
113-
.gitignore
114-
115-
log_info "Created $ARCHIVE_PATH"
116-
log_info "Contents:"
117-
tar -tzf "$ARCHIVE_PATH"
106+
create_tgz_from_staging "$STAGING_DIR" "$ARCHIVE_PATH"
118107

119108
end_group

0 commit comments

Comments
 (0)