Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 28 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ jobs:
arch: "x86_64"
triple: "x86_64-unknown-linux-gnu"
comprehensive_test: true
lint_check: true
- name: "Linux ARM64"
runner: ubuntu-24.04-arm
platform: "Linux"
arch: "aarch64"
triple: "aarch64-unknown-linux-gnu"
comprehensive_test: true
lint_check: true

steps:
- name: Checkout code
Expand Down Expand Up @@ -99,7 +101,30 @@ jobs:

if [ "${{ matrix.platform }}" = "macOS" ]; then
echo "Building universal macOS binary..."
swift build --configuration release --arch arm64 --arch x86_64 -Xswiftc -Osize

# Build ARM64 binary
echo "Building ARM64 binary..."
swift build --configuration release --arch arm64 -Xswiftc -Osize

# Build x86_64 binary
echo "Building x86_64 binary..."
swift build --configuration release --arch x86_64 -Xswiftc -Osize

# Create output directory
mkdir -p .build/apple/Products/Release

# Combine architectures with lipo
echo "Combining architectures with lipo..."
lipo -create \
.build/arm64-apple-macosx/release/swift-dependency-audit \
.build/x86_64-apple-macosx/release/swift-dependency-audit \
-output .build/apple/Products/Release/swift-dependency-audit

# Verify the universal binary
echo "Verifying universal binary..."
lipo -info .build/apple/Products/Release/swift-dependency-audit

# Strip the final binary
strip -rSTx .build/apple/Products/Release/swift-dependency-audit
else
echo "Building static Linux binary for ${{ matrix.arch }}..."
Expand Down Expand Up @@ -138,7 +163,7 @@ jobs:

echo "=== Testing JSON Output ==="
$BINARY_PATH . --output-format json --no-color --exclude-tests > output.json
cat output.json | python3 -m json.tool > /dev/null || (echo "❌ Invalid JSON output" && exit 1)
jq . output.json > /dev/null || (echo "❌ Invalid JSON output" && exit 1)
echo "✅ JSON output is valid"

echo "=== Testing Output Formats ==="
Expand All @@ -148,14 +173,7 @@ jobs:
echo "=== Testing Custom Whitelist ==="
$BINARY_PATH . --whitelist "Foundation,SwiftUI,ArgumentParser" --verbose --exclude-tests

echo "=== Testing Plugin Integration ==="
if swift package plugin --list | grep -q "DependencyAuditPlugin"; then
echo "✅ Plugin is properly registered"
else
echo "⚠️ Plugin not found in list, but core functionality works"
fi

- name: Lint and format check (macOS only)
- name: Lint and format check
if: matrix.lint_check
run: |
echo "=== Format Check ==="
Expand All @@ -165,16 +183,6 @@ jobs:
else
echo "swift-format not available, skipping format check"
fi

echo "=== Build Warnings Check ==="
swift build --configuration release 2>&1 | tee build.log
if grep -q "warning:" build.log; then
echo "⚠️ Build warnings found:"
grep "warning:" build.log
exit 1
else
echo "✅ No build warnings found"
fi
continue-on-error: true

- name: Upload build artifacts
Expand Down
44 changes: 34 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,30 @@ jobs:

if [ "${{ matrix.platform }}" = "macOS" ]; then
echo "Building universal macOS binary (version will be detected as: $VERSION)..."
swift build --configuration release --arch arm64 --arch x86_64 -Xswiftc -Osize

# Build ARM64 binary
echo "Building ARM64 binary..."
swift build --configuration release --arch arm64 -Xswiftc -Osize

# Build x86_64 binary
echo "Building x86_64 binary..."
swift build --configuration release --arch x86_64 -Xswiftc -Osize

# Create output directory
mkdir -p .build/apple/Products/Release

# Combine architectures with lipo
echo "Combining architectures with lipo..."
lipo -create \
.build/arm64-apple-macosx/release/swift-dependency-audit \
.build/x86_64-apple-macosx/release/swift-dependency-audit \
-output .build/apple/Products/Release/swift-dependency-audit

# Verify the universal binary
echo "Verifying universal binary..."
lipo -info .build/apple/Products/Release/swift-dependency-audit

# Strip the final binary
strip -rSTx .build/apple/Products/Release/swift-dependency-audit
else
echo "Building static Linux binary for ${{ matrix.arch }} (version will be detected as: $VERSION)..."
Expand Down Expand Up @@ -134,7 +157,7 @@ jobs:

echo "=== Testing JSON Output ==="
$BINARY_PATH . --output-format json --no-color --exclude-tests > output.json
cat output.json | python3 -m json.tool > /dev/null || (echo "❌ Invalid JSON output" && exit 1)
jq . output.json > /dev/null || (echo "❌ Invalid JSON output" && exit 1)
echo "✅ JSON output is valid"

echo "=== Testing Output Formats ==="
Expand All @@ -144,13 +167,6 @@ jobs:
echo "=== Testing Custom Whitelist ==="
$BINARY_PATH . --whitelist "Foundation,SwiftUI,ArgumentParser" --verbose --exclude-tests

echo "=== Testing Plugin Integration ==="
if swift package plugin --list | grep -q "DependencyAuditPlugin"; then
echo "✅ Plugin is properly registered"
else
echo "⚠️ Plugin not found in list, but core functionality works"
fi

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -290,7 +306,15 @@ jobs:
- name: Generate checksums
run: |
cd release
shasum -a 256 *.tar.gz > checksums.txt
# Use portable checksum command
if command -v shasum >/dev/null 2>&1; then
shasum -a 256 *.tar.gz > checksums.txt
elif command -v sha256sum >/dev/null 2>&1; then
sha256sum *.tar.gz > checksums.txt
else
echo "❌ No checksum tool available"
exit 1
fi
cat checksums.txt

- name: Generate release notes
Expand Down
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ clean:
# Build for current platform
.PHONY: build
build:
swift build $(SWIFT_BUILD_FLAGS)
VERSION=$(VERSION) swift build $(SWIFT_BUILD_FLAGS)

# Build universal macOS binary
.PHONY: build_macos
build_macos:
@echo "Building universal macOS binary..."
swift build $(SWIFT_BUILD_FLAGS) --arch arm64 --arch x86_64
VERSION=$(VERSION) swift build $(SWIFT_BUILD_FLAGS) --arch arm64 --arch x86_64
strip -rSTx $(MACOS_BUILD_DIR)/$(EXECUTABLE_NAME)
@echo "✅ macOS universal binary built at $(MACOS_BUILD_DIR)/$(EXECUTABLE_NAME)"

Expand All @@ -55,13 +55,13 @@ build_linux_native:
ifeq ($(shell uname -m), x86_64)
@echo "Building Linux x86_64 binary natively..."
mkdir -p $(LINUX_X86_64_BUILD_DIR)
swift build $(SWIFT_BUILD_FLAGS) --triple x86_64-unknown-linux-gnu --static-swift-stdlib
VERSION=$(VERSION) swift build $(SWIFT_BUILD_FLAGS) --triple x86_64-unknown-linux-gnu --static-swift-stdlib
strip .build/x86_64-unknown-linux-gnu/release/$(EXECUTABLE_NAME)
@echo "✅ Linux x86_64 binary built natively"
else ifeq ($(shell uname -m), aarch64)
@echo "Building Linux ARM64 binary natively..."
mkdir -p $(LINUX_AARCH64_BUILD_DIR)
swift build $(SWIFT_BUILD_FLAGS) --triple aarch64-unknown-linux-gnu --static-swift-stdlib
VERSION=$(VERSION) swift build $(SWIFT_BUILD_FLAGS) --triple aarch64-unknown-linux-gnu --static-swift-stdlib
strip .build/aarch64-unknown-linux-gnu/release/$(EXECUTABLE_NAME)
@echo "✅ Linux ARM64 binary built natively"
else
Expand All @@ -83,7 +83,7 @@ build_linux_x86_64:
-e HOME=/tmp \
swift:6.1 \
bash -c " \
swift build $(SWIFT_BUILD_FLAGS) --triple x86_64-unknown-linux-gnu --static-swift-stdlib && \
VERSION=$(VERSION) swift build $(SWIFT_BUILD_FLAGS) --triple x86_64-unknown-linux-gnu --static-swift-stdlib && \
strip .build/x86_64-unknown-linux-gnu/release/$(EXECUTABLE_NAME) \
"
@echo "✅ Linux x86_64 binary built at $(LINUX_X86_64_BUILD_DIR)/$(EXECUTABLE_NAME)"
Expand All @@ -102,7 +102,7 @@ build_linux_aarch64:
echo 'Installing cross-compilation tools...' && \
apt-get update && apt-get install -y gcc-aarch64-linux-gnu && \
echo 'Cross-compiling for ARM64...' && \
swift build $(SWIFT_BUILD_FLAGS) --triple aarch64-unknown-linux-gnu -Xcc -target -Xcc aarch64-unknown-linux-gnu --static-swift-stdlib -Xswiftc -resource-dir -Xswiftc /usr/lib/swift_static && \
VERSION=$(VERSION) swift build $(SWIFT_BUILD_FLAGS) --triple aarch64-unknown-linux-gnu -Xcc -target -Xcc aarch64-unknown-linux-gnu --static-swift-stdlib -Xswiftc -resource-dir -Xswiftc /usr/lib/swift_static && \
aarch64-linux-gnu-strip .build/aarch64-unknown-linux-gnu/release/$(EXECUTABLE_NAME) \
"
@echo "✅ Linux ARM64 binary built at $(LINUX_AARCH64_BUILD_DIR)/$(EXECUTABLE_NAME)"
Expand Down
12 changes: 12 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ let package = Package(
targets: [
.target(
name: "SwiftDependencyAuditLib",
plugins: ["VersionPlugin"]
),
.executableTarget(
name: "SwiftDependencyAudit",
Expand All @@ -41,6 +42,12 @@ let package = Package(
"SwiftDependencyAuditLib"
]
),
.executableTarget(
name: "VersionGenerator",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser")
]
),
.testTarget(
name: "SwiftDependencyAuditTests",
dependencies: ["SwiftDependencyAuditLib"]
Expand All @@ -50,6 +57,11 @@ let package = Package(
capability: .buildTool(),
dependencies: swiftDependencyAuditPluginDependencies
),
.plugin(
name: "VersionPlugin",
capability: .buildTool(),
dependencies: ["VersionGenerator"]
),
]
)

Expand Down
21 changes: 21 additions & 0 deletions Plugins/VersionPlugin/VersionPlugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Foundation
import PackagePlugin

@main
struct VersionPlugin: BuildToolPlugin {
func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
let versionGenerator = try context.tool(named: "VersionGenerator")
let versionFileURL = context.pluginWorkDirectoryURL.appending(path: "Version.swift")

return [
.buildCommand(
displayName: "Generate version information into \(versionFileURL.lastPathComponent)",
executable: versionGenerator.url,
arguments: [versionFileURL.path(percentEncoded: false)],
environment: ProcessInfo.processInfo.environment,
inputFiles: [],
outputFiles: [versionFileURL]
)
]
}
}
18 changes: 17 additions & 1 deletion Scripts/spm-artifact-bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ log_error() {
echo -e "${RED}❌ $*${NC}" >&2
}

# Utility functions
calculate_checksum() {
local file="$1"

if command -v shasum >/dev/null 2>&1; then
# macOS/BSD systems
shasum -a 256 "$file" | cut -d' ' -f1
elif command -v sha256sum >/dev/null 2>&1; then
# Linux/GNU systems
sha256sum "$file" | cut -d' ' -f1
else
log_error "No checksum tool available (shasum or sha256sum)"
return 1
fi
}

# Validation functions
validate_version() {
local version="$1"
Expand Down Expand Up @@ -257,7 +273,7 @@ main() {
fi

# Calculate checksum
local checksum=$(shasum -a 256 "$zip_name" | cut -d' ' -f1)
local checksum=$(calculate_checksum "$zip_name")
local zip_size=$(du -h "$zip_name" | cut -f1)

# Save checksum to file for CI
Expand Down
18 changes: 17 additions & 1 deletion Scripts/update-artifact-bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ log_error() {
echo -e "${RED}❌ $*${NC}" >&2
}

# Utility functions
calculate_checksum() {
local file="$1"

if command -v shasum >/dev/null 2>&1; then
# macOS/BSD systems
shasum -a 256 "$file" | cut -d' ' -f1
elif command -v sha256sum >/dev/null 2>&1; then
# Linux/GNU systems
sha256sum "$file" | cut -d' ' -f1
else
log_error "No checksum tool available (shasum or sha256sum)"
return 1
fi
}

# Validation functions
validate_version() {
local version="$1"
Expand Down Expand Up @@ -102,7 +118,7 @@ main() {

# Calculate and validate checksum
log_info "Calculating SHA256 checksum for $ARTIFACT_BUNDLE..."
local readonly checksum="$(shasum -a 256 "$ARTIFACT_BUNDLE" | cut -d " " -f1)"
local readonly checksum="$(calculate_checksum "$ARTIFACT_BUNDLE")"

if ! validate_checksum "$checksum"; then
exit 1
Expand Down
38 changes: 2 additions & 36 deletions Sources/SwiftDependencyAudit/DependentImportScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,10 @@ import Foundation

/// Get the version string, trying multiple sources
private func getVersion() -> String {
// First try to get version from git if available (for development)
if let gitVersion = getGitVersion() {
return gitVersion
}

// Fallback to embedded version
#if DEBUG
return "dev"
#else
return "1.0.0" // Fallback for release builds
#endif
// Always use the build-time generated version from the plugin
return SwiftDependencyAuditLib.VERSION
}

/// Attempt to get version from git (for development builds)
private func getGitVersion() -> String? {
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/git")
process.arguments = ["describe", "--tags", "--always"]

let pipe = Pipe()
process.standardOutput = pipe
process.standardError = Pipe() // Suppress error output

do {
try process.run()
process.waitUntilExit()

guard process.terminationStatus == 0 else { return nil }

let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)

// Remove 'v' prefix if present
return output?.hasPrefix("v") == true ? String(output!.dropFirst()) : output
} catch {
return nil
}
}

public enum OutputFormat: String, CaseIterable, ExpressibleByArgument {
case terminal = "terminal"
Expand Down
Loading