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
45 changes: 45 additions & 0 deletions .github/actions/generate-build-metadata/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Generate build metadata
description: Generate the Swift source containing release build metadata.

inputs:
version:
description: Version string to embed
required: true
commit-sha:
description: Commit SHA to embed
required: true
build-date:
description: Build date to embed
required: true

runs:
using: composite
steps:
- name: Generate build metadata
shell: bash
working-directory: ${{ github.workspace }}
env:
VERSION: ${{ inputs.version }}
COMMIT_SHA: ${{ inputs.commit-sha }}
BUILD_DATE: ${{ inputs.build-date }}
run: |
swift_string() {
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
}

VERSION=$(swift_string "$VERSION")
COMMIT_SHA=$(swift_string "$COMMIT_SHA")
BUILD_DATE=$(swift_string "$BUILD_DATE")

cat > Sources/CLI/main/BuildMetadata.swift <<EOF
enum BuildMetadata {
static let version = "$VERSION"
static let commit = "$COMMIT_SHA"
static let buildDate = "$BUILD_DATE"
static let environment = "production"

static let formatted =
"\\(version) (commit: \\(commit), built: \\(buildDate), environment: \\(environment))"
static let sentryRelease = "apple-docs@\\(version)+\\(commit)"
}
EOF
16 changes: 15 additions & 1 deletion .github/pre-release-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,24 @@ chmod +x apple-docs
sudo mv apple-docs /usr/local/bin/
```

#### Linux

```bash
# AMD64
curl -L -o apple-docs https://github.com/{{REPOSITORY}}/releases/download/latest/apple-docs-linux-amd64
chmod +x apple-docs
sudo mv apple-docs /usr/local/bin/

# ARM64
curl -L -o apple-docs https://github.com/{{REPOSITORY}}/releases/download/latest/apple-docs-linux-arm64
chmod +x apple-docs
sudo mv apple-docs /usr/local/bin/
```

### What's New?

See the [commit history](https://github.com/{{REPOSITORY}}/commits/main) for recent changes.

### Checksums

See `checksums.txt` for SHA256 checksums of both binaries.
See `checksums.txt` for SHA256 checksums of all binaries.
34 changes: 33 additions & 1 deletion .github/release-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,40 @@ chmod +x apple-docs
sudo mv apple-docs /usr/local/bin/
```

#### Linux (DNF/YUM)

```bash
sudo dnf config-manager --add-repo https://packages.techprimate.com/techprimate.repo
sudo dnf install apple-docs
```

#### Linux (APT)

```bash
sudo curl -fsSL https://packages.techprimate.com/RPM-GPG-KEY-techprimate \
| sudo gpg --dearmor -o /usr/share/keyrings/techprimate-archive-keyring.gpg
sudo curl -fsSL https://packages.techprimate.com/techprimate.sources \
-o /etc/apt/sources.list.d/techprimate.sources
sudo apt update
sudo apt install apple-docs
```

#### Linux (Manual)

```bash
# AMD64
curl -L -o apple-docs https://github.com/{{REPOSITORY}}/releases/download/v{{VERSION}}/apple-docs-linux-amd64
chmod +x apple-docs
sudo mv apple-docs /usr/local/bin/

# ARM64
curl -L -o apple-docs https://github.com/{{REPOSITORY}}/releases/download/v{{VERSION}}/apple-docs-linux-arm64
chmod +x apple-docs
sudo mv apple-docs /usr/local/bin/
```

See the [README](https://github.com/{{REPOSITORY}}/blob/main/README.md) for more details.

### Checksums

See `checksums.txt` for SHA256 checksums of both binaries.
See `checksums.txt` for SHA256 checksums of all binaries.
86 changes: 61 additions & 25 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,31 +51,11 @@ jobs:
swift-version: "6.3.3"

- name: Generate build metadata
env:
VERSION: ${{ inputs.version }}
COMMIT_SHA: ${{ inputs.commit_sha }}
BUILD_DATE: ${{ inputs.build_date }}
run: |
swift_string() {
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
}

VERSION=$(swift_string "$VERSION")
COMMIT_SHA=$(swift_string "$COMMIT_SHA")
BUILD_DATE=$(swift_string "$BUILD_DATE")

cat > Sources/CLI/main/BuildMetadata.swift <<EOF
enum BuildMetadata {
static let version = "$VERSION"
static let commit = "$COMMIT_SHA"
static let buildDate = "$BUILD_DATE"
static let environment = "production"

static let formatted =
"\\(version) (commit: \\(commit), built: \\(buildDate), environment: \\(environment))"
static let sentryRelease = "apple-docs@\\(version)+\\(commit)"
}
EOF
uses: ./.github/actions/generate-build-metadata
with:
version: ${{ inputs.version }}
commit-sha: ${{ inputs.commit_sha }}
build-date: ${{ inputs.build_date }}

- name: Build CLI
id: build
Expand Down Expand Up @@ -127,6 +107,62 @@ jobs:
if-no-files-found: error
retention-days: 1

build-linux:
name: Build ${{ matrix.platform }}
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
matrix:
include:
- platform: linux-amd64
swift_sdk: x86_64-swift-linux-musl
- platform: linux-arm64
swift_sdk: aarch64-swift-linux-musl
steps:
- name: Checkout
uses: actions/checkout@v7

- name: Setup Swift
uses: swift-actions/setup-swift@v3
with:
swift-version: "6.3.3"

- name: Install Static Linux SDK
run: |
swift sdk install \
"https://download.swift.org/swift-6.3.3-release/static-sdk/swift-6.3.3-RELEASE/swift-6.3.3-RELEASE_static-linux-0.1.0.artifactbundle.tar.gz" \
--checksum "87c3eaf908e67c0e13a84367119e12273cec1d2cd3d81f7d74bb36722d6b607b"

- name: Generate build metadata
uses: ./.github/actions/generate-build-metadata
with:
version: ${{ inputs.version }}
commit-sha: ${{ inputs.commit_sha }}
build-date: ${{ inputs.build_date }}

- name: Build CLI
run: |
swift build -c release --swift-sdk "${{ matrix.swift_sdk }}"
BIN_DIR=$(swift build -c release --swift-sdk "${{ matrix.swift_sdk }}" --show-bin-path)
mkdir -p dist
cp "$BIN_DIR/apple-docs" "dist/apple-docs-${{ matrix.platform }}"

- name: Exercise Linux CLI
if: matrix.platform == 'linux-amd64'
run: |
"dist/apple-docs-${{ matrix.platform }}" \
types view String --technology Swift --json \
> "$RUNNER_TEMP/string.json"
jq -e '.metadata.title == "String"' "$RUNNER_TEMP/string.json"

- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: cli-${{ matrix.platform }}
path: dist/apple-docs-${{ matrix.platform }}
if-no-files-found: error
retention-days: 1

sign-and-notarize-darwin:
name: Sign and Notarize macOS Binaries
if: github.event_name != 'pull_request'
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ jobs:
files: |
dist/apple-docs-darwin-amd64
dist/apple-docs-darwin-arm64
dist/apple-docs-linux-amd64
dist/apple-docs-linux-arm64
dist/checksums.txt
draft: false
prerelease: ${{ needs.prepare.outputs.is_prerelease == 'true' }}
Expand All @@ -153,7 +155,7 @@ jobs:
name: Trigger Release Publisher
needs: [prepare, release]
# Dispatch the techprimate/publisher workflow that publishes this GitHub
# Release through packages.techprimate.app. Replaces the in-repo Homebrew tap
# Release through packages.techprimate.com. Replaces the in-repo Homebrew tap
# automation.
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,19 @@ jobs:

- name: Make Test
run: make test

test-linux:
name: Test Linux
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v7

- name: Setup Swift
uses: swift-actions/setup-swift@v3
with:
swift-version: "6.3.3"

- name: Make Test
run: make test
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ run:
test:
swift test

## Run all tests in a Linux container
#
# Uses a Docker volume for SwiftPM build output so Linux artifacts do not conflict
# with the host build directory.
.PHONY: test-linux
test-linux:
docker run --rm \
--mount "type=bind,source=$(CURDIR),target=/workspace,readonly" \
--volume "apple-docs-cli-linux-build:/workspace/.build" \
--workdir /workspace \
swift:6.3.3 \
swift test --disable-automatic-resolution

## Run live CLI integration tests
#
# Builds the release executable and runs network-dependent command tests against Apple documentation.
Expand Down
41 changes: 26 additions & 15 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

import PackageDescription

let package = Package(
name: "apple-docs-cli",
platforms: [.macOS(.v13)],
products: [
.executable(name: "apple-docs", targets: ["CLI"])
],
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.8.2"),
.package(url: "https://github.com/apple/swift-log.git", exact: "1.15.1"),
var packageDependencies: [Package.Dependency] = [
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.8.2"),
.package(url: "https://github.com/apple/swift-log.git", exact: "1.15.1"),
]
var cliDependencies: [Target.Dependency] = [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "Logging", package: "swift-log"),
]

#if os(macOS)
packageDependencies += [
.package(
url: "https://github.com/getsentry/sentry-apple-swift-log.git",
exact: "9.28.0",
Expand All @@ -21,16 +23,25 @@ let package = Package(
exact: "9.28.0",
traits: ["NoUIFramework"]
),
]
cliDependencies += [
.product(name: "SentrySwiftLog", package: "sentry-apple-swift-log"),
.product(name: "SentrySPM", package: "sentry-cocoa"),
]
#endif

let package = Package(
name: "apple-docs-cli",
platforms: [.macOS(.v13)],
products: [
.executable(name: "apple-docs", targets: ["CLI"])
],
dependencies: packageDependencies,
targets: [
.executableTarget(
name: "CLI",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "Logging", package: "swift-log"),
.product(name: "SentrySwiftLog", package: "sentry-apple-swift-log"),
.product(name: "SentrySPM", package: "sentry-cocoa"),
]),
dependencies: cliDependencies
),
.testTarget(name: "CLITests", dependencies: ["CLI"]),
.testTarget(name: "CLIIntegrationTests"),
],
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# apple-docs-cli

`apple-docs-cli` is a stateless macOS CLI for retrieving Apple Developer documentation for known API types. It fetches Apple’s DocC JSON and renders a concise terminal view or returns the raw document for further processing.
`apple-docs-cli` is a stateless macOS and Linux CLI for retrieving Apple Developer documentation for known API types. It fetches Apple’s DocC JSON and renders a concise terminal view or returns the raw document for further processing.

## Type documentation

Expand Down Expand Up @@ -104,6 +104,12 @@ make test
make analyze
```

Run the test suite in a pinned Linux Swift container:

```bash
make test-linux
```

Format Swift with `swift format` and JSON, YAML, Markdown, and TOML with dprint:

```bash
Expand Down
4 changes: 4 additions & 0 deletions Sources/CLI/cache/DocumentationCache.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import Foundation

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

#if DEBUG
protocol DocumentationCache {
var currentDiskUsage: Int { get }
Expand Down
4 changes: 4 additions & 0 deletions Sources/CLI/client/AppleDocumentationClient.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import Foundation

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

#if DEBUG
protocol AppleDocumentationClient: Sendable {
func fetchType(named name: String, technology: String) async throws -> TypeDocumentationDocument
Expand Down
4 changes: 4 additions & 0 deletions Sources/CLI/client/DocumentationTypeCatalogClient.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import Foundation

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

#if DEBUG
protocol DocumentationTypeCatalogClient: Sendable {
func fetchTypes(technology: String) async throws -> [DocumentationType]
Expand Down
4 changes: 4 additions & 0 deletions Sources/CLI/client/DocumentationTypeSearchClient.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import Foundation

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

#if DEBUG
protocol DocumentationTypeSearchClient: Sendable {
func searchTypes(query: String, technology: String) async throws -> [DocumentationType]
Expand Down
Loading
Loading