Skip to content

Commit

Permalink
Additional package infrastructure work (#6)
Browse files Browse the repository at this point in the history
* Add SPDX license header to all source files. Also remove many many unnecessary instances of "import Foundation"

* Add updating of OS packages to Dockerfile

* Add soundness check and API breakage check scripts.

* Retool soundness script to do fancy rules-based stuff for license header checks, because why the heck not

* Make GH Actions workflow do tests and such

* Include derivation notice and derivation source license headers as required by Apache 2.0.

* Specify sufficiently new macOS runner, disable tests on Linux for now due to XCTest lacking async support

* add missing workaround for XCTest brokenness annoyances

* Enable back-deployment for concurrency, hopefully.

* Fix percent encoding handling of filter strings correctly by adding workaround implementation of `URLComponents.percentEncodedQueryItems` where it's needed.

* Add workaround to the async test method so the tests can run on Linux, and reenable Linux testing.
  • Loading branch information
gwynne committed Dec 2, 2021
1 parent b84f5b3 commit ac651bb
Show file tree
Hide file tree
Showing 63 changed files with 915 additions and 283 deletions.
13 changes: 0 additions & 13 deletions .github/workflows/linux.yml

This file was deleted.

43 changes: 43 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: test
on:
pull_request:

jobs:
linux:
runs-on: ubuntu-latest
container: swift:5.5-focal
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Run tests with Thread Sanitizer
run: swift test --enable-test-discovery --sanitize=thread
- name: Verify release build
timeout-minutes: 30
run: swift build -c release

macos:
runs-on: macos-11
steps:
- name: Select latest available Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest
- name: Check out code
uses: actions/checkout@v2
- name: Run tests
timeout-minutes: 30
run: |
swift test -Xlinker -rpath \
-Xlinker $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx
# windows:
# runs-on: windows-latest
# steps:
# - uses: compnerd/gha-setup-swift@main
# with:
# branch: swift-5.5-release
# tag: 5.5-RELEASE
# - name: Check out code
# uses: actions/checkout@v2
# - name: Run tests
# run: swift test
25 changes: 23 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
##===----------------------------------------------------------------------===##
##
## This source file is part of the OneRoster open source project
##
## Copyright (c) 2021 the OneRoster project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##

# Build image
# ================================
FROM swift:5.5.1-focal as build
FROM swift:5.5-focal as build

# Install OS updates
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
&& apt-get -q update \
&& apt-get -q dist-upgrade -y \
&& rm -rf /var/lib/apt/lists/*

# Set up a build area
WORKDIR /build

# First just resolve dependencies.
Expand All @@ -14,4 +35,4 @@ RUN swift package resolve
COPY . .

# Compile with optimizations
RUN swift build -c release
RUN swift build -c release
File renamed without changes.
27 changes: 27 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

The Swift OneRoster Client Project
==================================

Copyright The Swift OneRoster Client Project

The Swift OneRoster Client Project licenses this file to you under the
Apache License, version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the
License at:

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.

-------------------------------------------------------------------------------

This product contains a derivation of various scripts from SwiftNIO.

* LICENSE (Apache License 2.0):
* https://www.apache.org/licenses/LICENSE-2.0
* HOMEPAGE:
* https://github.com/apple/swift-nio
17 changes: 15 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
// swift-tools-version:5.5
//===----------------------------------------------------------------------===//
//
// This source file is part of the OneRoster open source project
//
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import PackageDescription

let package = Package(
name: "OneRoster",
platforms: [
.macOS(.v12)
.macOS(.v11),
],
products: [
.library(name: "OneRoster", targets: ["OneRoster"]),
Expand All @@ -21,6 +34,6 @@ let package = Package(
.testTarget(name: "OneRosterTests", dependencies: [
.target(name: "OneRoster"),
.product(name: "XCTVapor", package: "vapor"),
])
]),
]
)
13 changes: 10 additions & 3 deletions Sources/OneRoster/Client/Application+OneRosterClient.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
//===----------------------------------------------------------------------===//
//
// Application+OneRosterClient.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Created by Jimmy McDermott on 4/10/20.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation
import Vapor

@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
extension Application {
/// Get a `OneRosterClient` suitable for making OneRoster requests to the given base URL without authentication.
///
Expand Down
12 changes: 9 additions & 3 deletions Sources/OneRoster/Client/OAuth1.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
//===----------------------------------------------------------------------===//
//
// OAuth1.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Copyright Slate Solutions, Inc 2021.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation
import Vapor
Expand Down
12 changes: 9 additions & 3 deletions Sources/OneRoster/Client/OAuth2.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
//===----------------------------------------------------------------------===//
//
// OAuth2.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Copyright Slate Solutions, Inc 2021.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation
import Vapor
Expand Down
12 changes: 9 additions & 3 deletions Sources/OneRoster/Client/OneRosterAPI.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
//===----------------------------------------------------------------------===//
//
// OneRosterAPI.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Copyright Slate Solutions, Inc 2019.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation

Expand Down
45 changes: 37 additions & 8 deletions Sources/OneRoster/Client/OneRosterClient.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
//===----------------------------------------------------------------------===//
//
// OneRosterClient.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Copyright Slate Solutions, Inc 2019.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation
import Crypto
import Vapor
import Logging

@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
public struct OneRosterClient {
public let baseUrl: URL
public let client: Client
Expand Down Expand Up @@ -146,9 +153,31 @@ extension URLComponents {
/// Add a `URLQueryItem` with the given percent-encoded name and value to the `percentEncodedQueryItems` component.
///
/// The `percentEncodedQueryItems` array is created if it is currently `nil`.
// public mutating func appendPercentEncodedQueryItem(name: String, value: String? = nil) {
// self.percentEncodedQueryItems = (self.percentEncodedQueryItems ?? []) + [URLQueryItem(name: name, value: value)]
// }
public mutating func appendPercentEncodedQueryItem(name: String, value: String? = nil) {
self.percentEncodedQueryItems = (self.percentEncodedQueryItems ?? []) + [URLQueryItem(name: name, value: value)]
}

#if os(Linux) && swift(<5.6)
public var percentEncodedQueryItems: [URLQueryItem]? {
get {
guard let percentEncodedQuery = self.percentEncodedQuery else {
return nil
}
// Since the query string is already percent-encoded, we don't have to do anything fancy to
// parse it out; surprisingly, and conveniently, simple string splitting is plenty.
return percentEncodedQuery.split(separator: "&", maxSplits: .max, omittingEmptySubsequences: true).map {
$0.split(separator: "=", maxSplits: 1, omittingEmptySubsequences: false)
}.map {
URLQueryItem(name: String($0[0]), value: $0.last.map(String.init))
}
}
set {
// Since the individual items are already percent-encoded, we can do simple joins to construct
// the query string. Again, surprisingly convenient.
self.percentEncodedQuery = newValue?.map { i in i.value.map { "\(i.name)=\($0)" } ?? i.name }.joined(separator: "&")
}
}
#endif
}

extension OneRosterAPI.Endpoint {
Expand All @@ -168,8 +197,8 @@ extension OneRosterAPI.Endpoint {
if let offset = offset {
components.appendQueryItem(name: "offset", value: "\(offset)")
}
if let filterString = filterString, let encoded = filterString.addingPercentEncoding(withAllowedCharacters: .alphanumerics) {
components.appendQueryItem(name: "filter", value: encoded)
if let filterString = filterString {
components.appendPercentEncodedQueryItem(name: "filter", value: filterString)
}

guard var paramUrl = components.url else {
Expand Down
13 changes: 10 additions & 3 deletions Sources/OneRoster/Client/Request+OneRosterClient.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
//===----------------------------------------------------------------------===//
//
// Request+OneRosterClient.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Created by Jimmy McDermott on 4/10/20.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation
import Vapor

@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
extension Request {
/// Get a `OneRosterClient` suitable for making OneRoster requests to the given base URL without authentication.
///
Expand Down
15 changes: 9 additions & 6 deletions Sources/OneRoster/Enumerations/ClassType.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
//===----------------------------------------------------------------------===//
//
// ClassType.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Copyright Slate Solutions, Inc 2019.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//

import Foundation
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

/// The set of permitted tokens for the type of class
public enum ClassType: String, Codable {

/// The homeroom (form) assigned to the class.
case homeroom

Expand Down
15 changes: 9 additions & 6 deletions Sources/OneRoster/Enumerations/GUIDType.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
//===----------------------------------------------------------------------===//
//
// GUIDType.swift
// OneRoster
// This source file is part of the OneRoster open source project
//
// Copyright Slate Solutions, Inc 2019.
// Copyright (c) 2021 the OneRoster project authors
// Licensed under Apache License v2.0
//

import Foundation
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

/// Describes the entity type of a returned GUIDRef
public enum GUIDType: String, Codable {

/// An AcademicSession
case academicSession

Expand Down
Loading

0 comments on commit ac651bb

Please sign in to comment.