Skip to content

Add author and signer to package collection models #6415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 12, 2023
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
9 changes: 9 additions & 0 deletions Fixtures/Collections/JSON/good.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@
"name": "Apache-2.0",
"url": "https://www.example.com/repos/RepoOne/LICENSE"
},
"author": {
"name": "J. Appleseed"
},
"signer": {
"type": "ADP",
"commonName": "J. Appleseed",
"organizationalUnitName": "A1",
"organizationName": "Appleseed Inc."
},
"createdAt": "2020-10-21T09:25:36Z"
}
]
Expand Down
9 changes: 9 additions & 0 deletions Fixtures/Collections/JSON/good_signed.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@
"name": "Apache-2.0",
"url": "https://www.example.com/repos/RepoOne/LICENSE"
},
"author": {
"name": "J. Appleseed"
},
"signer": {
"type": "ADP",
"commonName": "J. Appleseed",
"organizationalUnitName": "A1",
"organizationName": "Appleseed Inc."
},
"createdAt": "2020-10-21T09:25:36Z"
}
]
Expand Down
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ let package = Package(
"PackageCollections",
"PackageModel",
"PackageRegistry",
"PackageSigning",
]
),

Expand Down
35 changes: 35 additions & 0 deletions Sources/PackageCollections/Model/PackageTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ extension PackageCollectionsModel.Package {

/// The package version's author
public let author: PackageCollectionsModel.Package.Author?

/// The package version's signer
public let signer: PackageCollectionsModel.Signer?

/// When the package version was created
public let createdAt: Date?
Expand Down Expand Up @@ -224,6 +227,38 @@ extension PackageCollectionsModel.Package {
}
}

extension PackageCollectionsModel {
public struct Signer: Equatable, Codable {
/// The signer type.
public let type: SignerType

/// The common name of the signing certificate's subject.
public let commonName: String

/// The organizational unit name of the signing certificate's subject.
public let organizationalUnitName: String

/// The organization name of the signing certificate's subject.
public let organizationName: String

public init(
type: SignerType,
commonName: String,
organizationalUnitName: String,
organizationName: String
) {
self.type = type
self.commonName = commonName
self.organizationalUnitName = organizationalUnitName
self.organizationName = organizationName
}
}

public enum SignerType: String, Codable {
case adp // Apple Developer Program
}
}

extension PackageCollectionsModel {
public typealias PackageMetadata = (package: PackageCollectionsModel.Package, collections: [PackageCollectionsModel.CollectionIdentifier], provider: PackageMetadataProviderContext?)
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/PackageCollections/PackageCollections.swift
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,8 @@ public struct PackageCollections: PackageCollectionsProtocol, Closable {
defaultToolsVersion: packageVersion.defaultToolsVersion,
verifiedCompatibility: packageVersion.verifiedCompatibility,
license: packageVersion.license,
author: versionMetadata?.author,
author: versionMetadata?.author ?? packageVersion.author,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Author info can come from GitHub or package collection

signer: packageVersion.signer,
createdAt: versionMetadata?.createdAt ?? packageVersion.createdAt)
}
versions.sort(by: >)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,27 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider {
}
let license = version.license.flatMap { Model.License(from: $0) }

let signer: Model.Signer?
if let versionSigner = version.signer, let signerType = Model.SignerType(rawValue: versionSigner.type.lowercased()) {
signer = .init(
type: signerType,
commonName: versionSigner.commonName,
organizationalUnitName: versionSigner.organizationalUnitName,
organizationName: versionSigner.organizationName
)
} else {
signer = nil
}

return .init(version: parsedVersion,
title: nil,
summary: version.summary,
manifests: manifests,
defaultToolsVersion: defaultToolsVersion,
verifiedCompatibility: verifiedCompatibility,
license: license,
author: nil,
author: version.author.map { .init(username: $0.name, url: nil, service: nil) },
signer: signer,
createdAt: version.createdAt)
}
if versions.count != package.versions.count {
Expand Down
7 changes: 7 additions & 0 deletions Sources/PackageCollectionsModel/Formats/v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ A version object has metadata extracted from `Package.swift` and optionally addi
* `license`: The package version's license. **Optional.**
* `url`: The URL of the license file.
* `name`: License name. [SPDX identifier](https://spdx.org/licenses/) (e.g., `Apache-2.0`, `MIT`, etc.) preferred. Omit if unknown. **Optional.**
* `author`: The package version's author. **Optional.**
* `name`: The author of the package version.
* `signer`: The signer of the package version. **Optional.** Refer to [documentation](https://github.com/apple/swift-package-manager/blob/main/Documentation/PackageRegistryUsage.md#package-signing) on package signing for details.
* `type`: The signer type. Currently the only valid value is `ADP` (Apple Developer Program).
* `commonName`: The common name of the signing certificate's subject.
* `organizationalUnitName`: The organizational unit name of the signing certificate's subject.
* `organizationName`: The organization name of the signing certificate's subject.
* `createdAt`: The ISO 8601-formatted datetime string when the package version was created. **Optional.**

##### Version-specific manifests
Expand Down
46 changes: 46 additions & 0 deletions Sources/PackageCollectionsModel/PackageCollectionModel+v1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ extension PackageCollectionModel.V1.Collection.Package {
/// The package version's license.
public let license: PackageCollectionModel.V1.License?

/// The author of the package version.
public let author: Author?

/// The signer of the package version.
public let signer: PackageCollectionModel.V1.Signer?

/// When the package version was created.
public let createdAt: Date?

Expand All @@ -152,6 +158,8 @@ extension PackageCollectionModel.V1.Collection.Package {
defaultToolsVersion: String,
verifiedCompatibility: [PackageCollectionModel.V1.Compatibility]?,
license: PackageCollectionModel.V1.License?,
author: Author?,
signer: PackageCollectionModel.V1.Signer?,
createdAt: Date?
) {
self.version = version
Expand All @@ -160,6 +168,8 @@ extension PackageCollectionModel.V1.Collection.Package {
self.defaultToolsVersion = defaultToolsVersion
self.verifiedCompatibility = verifiedCompatibility
self.license = license
self.author = author
self.signer = signer
self.createdAt = createdAt
}

Expand Down Expand Up @@ -194,6 +204,16 @@ extension PackageCollectionModel.V1.Collection.Package {
self.minimumPlatformVersions = minimumPlatformVersions
}
}

public struct Author: Equatable, Codable {
/// The author name.
public let name: String

/// Creates an `Author`
public init(name: String) {
self.name = name
}
}
}
}

Expand Down Expand Up @@ -286,6 +306,32 @@ extension PackageCollectionModel.V1 {
self.url = url
}
}

public struct Signer: Equatable, Codable {
/// The signer type. (e.g., ADP)
public let type: String

/// The common name of the signing certificate's subject.
public let commonName: String

/// The organizational unit name of the signing certificate's subject.
public let organizationalUnitName: String

/// The organization name of the signing certificate's subject.
public let organizationName: String

public init(
type: String,
commonName: String,
organizationalUnitName: String,
organizationName: String
) {
self.type = type
self.commonName = commonName
self.organizationalUnitName = organizationalUnitName
self.organizationName = organizationName
}
}
}

extension PackageCollectionModel.V1.Platform: Hashable {
Expand Down
61 changes: 54 additions & 7 deletions Sources/PackageMetadata/PackageMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Dispatch
import PackageCollections
import PackageModel
import PackageRegistry
import PackageSigning
import SourceControl

import struct Foundation.Date
Expand Down Expand Up @@ -72,6 +73,7 @@ public struct Package {
public let author: Author?
public let description: String?
public let publishedAt: Date?
public let signingEntity: SigningEntity?
public let latestVersion: Version?

fileprivate init(
Expand All @@ -86,6 +88,7 @@ public struct Package {
author: Author?,
description: String?,
publishedAt: Date?,
signingEntity: SigningEntity?,
latestVersion: Version? = nil,
source: Source
) {
Expand All @@ -100,6 +103,7 @@ public struct Package {
self.author = author
self.description = description
self.publishedAt = publishedAt
self.signingEntity = signingEntity
self.latestVersion = latestVersion
self.source = source
}
Expand Down Expand Up @@ -150,6 +154,7 @@ public struct PackageSearchClient {
public let author: Package.Author?
public let description: String?
public let publishedAt: Date?
public let signingEntity: SigningEntity?
}

private func getVersionMetadata(
Expand All @@ -172,7 +177,8 @@ public struct PackageSearchClient {
resources: metadata.resources.map { .init($0) },
author: metadata.author.map { .init($0) },
description: metadata.description,
publishedAt: metadata.publishedAt
publishedAt: metadata.publishedAt,
signingEntity: metadata.sourceArchive?.signingEntity
)
})
}
Expand All @@ -189,18 +195,22 @@ public struct PackageSearchClient {
self.indexAndCollections.findPackages(query) { result in
do {
let packages = try result.get().items.map {
Package(
let versions = $0.package.versions.sorted(by: >)
let latestVersion = versions.first

return Package(
identity: $0.package.identity,
location: $0.package.location,
versions: $0.package.versions.map(\.version),
licenseURL: nil,
licenseURL: $0.package.license?.url,
readmeURL: $0.package.readmeURL,
repositoryURLs: nil,
resources: [],
author: nil,
description: nil,
publishedAt: nil,
latestVersion: nil,
author: latestVersion?.author.map { .init($0) },
description: latestVersion?.summary,
publishedAt: latestVersion?.createdAt,
signingEntity: latestVersion?.signer.map { SigningEntity(signer: $0) },
latestVersion: latestVersion?.version,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can set some of these using the package's latest version listed in the collection/index result.

// this only makes sense in connection with providing versioned metadata
source: .indexAndCollections(collections: $0.collections, indexes: $0.indexes)
)
Expand Down Expand Up @@ -259,6 +269,7 @@ public struct PackageSearchClient {
author: nil,
description: nil,
publishedAt: nil,
signingEntity: nil,
latestVersion: nil,
// this only makes sense in connection with providing versioned metadata
source: .sourceControl(url: url)
Expand Down Expand Up @@ -298,6 +309,7 @@ public struct PackageSearchClient {
let author: Package.Author?
let description: String?
let publishedAt: Date?
let signingEntity: SigningEntity?
if case .success(let metadata) = result {
licenseURL = metadata.licenseURL
readmeURL = metadata.readmeURL
Expand All @@ -306,6 +318,7 @@ public struct PackageSearchClient {
author = metadata.author
description = metadata.description
publishedAt = metadata.publishedAt
signingEntity = metadata.signingEntity
} else {
licenseURL = nil
readmeURL = self.guessReadMeURL(alternateLocations: metadata.alternateLocations)
Expand All @@ -314,6 +327,7 @@ public struct PackageSearchClient {
author = nil
description = nil
publishedAt = nil
signingEntity = nil
}

return callback(.success([Package(
Expand All @@ -326,6 +340,7 @@ public struct PackageSearchClient {
author: author,
description: description,
publishedAt: publishedAt,
signingEntity: signingEntity,
latestVersion: version,
source: .registry(url: metadata.registry.url)
)]))
Expand All @@ -342,6 +357,7 @@ public struct PackageSearchClient {
author: nil,
description: nil,
publishedAt: nil,
signingEntity: nil,
latestVersion: nil,
// this only makes sense in connection with providing versioned metadata
source: .registry(url: metadata.registry.url)
Expand Down Expand Up @@ -426,6 +442,16 @@ extension Package.Author {
url: author.url
)
}

fileprivate init(_ author: PackageCollectionsModel.Package.Author) {
self.init(
name: author.username,
email: nil,
description: nil,
organization: nil,
url: author.url
)
}
}

extension Package.Organization {
Expand All @@ -438,3 +464,24 @@ extension Package.Organization {
)
}
}

extension SigningEntity {
fileprivate init(signer: PackageCollectionsModel.Signer) {
// All package collection signers are "recognized"
self = .recognized(
type: .init(signer.type),
name: signer.commonName,
organizationalUnit: signer.organizationalUnitName,
organization: signer.organizationName
)
}
}

extension SigningEntityType {
fileprivate init(_ type: PackageCollectionsModel.SignerType) {
switch type {
case .adp:
self = .adp
}
}
}
Loading