Skip to content

Commit

Permalink
add issue checker
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiocampama committed May 7, 2022
1 parent 0ad52ee commit dca1c36
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 52 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
.swiftpm
.swiftpm
*.json
33 changes: 29 additions & 4 deletions Sources/copilot-action/CopilotAction.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import APIBuilder
import ArgumentParser
import Foundation

@main
struct CopilotAction: AsyncParsableCommand {
Expand All @@ -7,11 +9,34 @@ struct CopilotAction: AsyncParsableCommand {
abstract: "Github Action main entry point for copilot-ios",
subcommands: [
PRSizeLabeler.self,
],
defaultSubcommand: PRSizeLabeler.self
IssueChecker.self,
]
)
}

extension ParsableCommand {
func getEnv(_ key: String, defaultValue: String? = nil) throws -> String {
guard let value = ProcessInfo.processInfo.environment[key] ?? defaultValue else {
throw StringError("\(key) environment variable not set")
}

return value
}

func getInputEnv(_ key: String, defaultValue: String? = nil) throws -> String {
guard let value = ProcessInfo.processInfo.environment["INPUT_" + key] ?? defaultValue else {
throw StringError("\(key) environment variable not set")
}

return value
}

func getInputEnv(_ key: String, defaultValue: Int? = nil) throws -> Int {
let envValue = ProcessInfo.processInfo.environment["INPUT_" + key]
guard let value = envValue.flatMap({ Int($0) }) ?? defaultValue else {
throw StringError("\(key) environment variable not set")
}

func run() async throws {
print("hello world!")
return value
}
}
19 changes: 19 additions & 0 deletions Sources/copilot-action/GithubConfiguration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import APIBuilder
import Foundation

struct GithubConfiguration: APIConfiguration {
let host = URL(string: "https://api.github.com")!

var requestHeaders: [String : String] {
[
"Content-Type": "application/vnd.github.v3+json",
"Authorization": "Bearer \(token)",
]
}

let token: String

init(token: String) {
self.token = token
}
}
61 changes: 61 additions & 0 deletions Sources/copilot-action/IssueChecker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import APIBuilder
import ArgumentParser
import Foundation

// MARK: - API Types

fileprivate struct PullRequestEvent: Codable {
fileprivate struct PullRequest: Codable {
fileprivate struct Head: Codable {
let ref: String
}
let body: String
let title: String
let head: Head
}
let pull_request: PullRequest
}

struct IssueChecker: AsyncParsableCommand {
static var configuration = CommandConfiguration(
commandName: "issue-checker"
)

func run() async throws {
let eventPath = try getEnv("GITHUB_EVENT_PATH")

guard let eventData = try String(contentsOfFile: eventPath).data(using: .utf8) else {
throw StringError("could not load event data at \(eventPath)")
}

let pullRequestEvent = try JSONDecoder().decode(PullRequestEvent.self, from: eventData)

print(pullRequestEvent.pull_request.body)
print(pullRequestEvent.pull_request.title)
print(pullRequestEvent.pull_request.head.ref)

let issuePrefix = try getInputEnv("ISSUE_CHECKER_PREFIX") as String

let inputsToCheck = [
pullRequestEvent.pull_request.body,
pullRequestEvent.pull_request.title,
pullRequestEvent.pull_request.head.ref,
]

for input in inputsToCheck {
let range = input
.lowercased()
.range(
of: "\(issuePrefix.lowercased())\\d{1,}",
options: .regularExpression
)

if let range = range {
print("Found \(input[range])")
return
}
}

throw StringError("Could not find issue in the PR")
}
}
72 changes: 26 additions & 46 deletions Sources/copilot-action/PRSizeLabeler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import ArgumentParser
import APIBuilder
import Foundation

struct PullRequest: Codable {
let additions: Int
let deletions: Int
}
// MARK: - API Types

fileprivate struct PullRequestEvent: Codable {
fileprivate struct PullRequest: Codable {
let additions: Int
let deletions: Int
}

struct PullRequestEvent: Codable {
let pull_request: PullRequest
let number: Int
}
Expand All @@ -16,22 +18,7 @@ struct LabelsChangeRequest: Codable {
let labels: [String]
}

struct GithubConfiguration: APIConfiguration {
let host = URL(string: "https://api.github.com")!

var requestHeaders: [String : String] {
[
"Content-Type": "application/vnd.github.v3+json",
"Authorization": "Bearer \(token)",
]
}

let token: String

init(token: String) {
self.token = token
}
}
// MARK: - Endpoints

extension APIEndpoint {
static func setLabels(repo: String, pullRequestID: Int) -> Self {
Expand All @@ -48,48 +35,41 @@ struct PRSizeLabeler: AsyncParsableCommand {
)

func run() async throws {
let githubToken = try getEnv(key: "GITHUB_TOKEN")
let repo = try getEnv(key: "GITHUB_REPOSITORY")
let eventPath = try getEnv(key: "GITHUB_EVENT_PATH")
let githubToken = try getEnv("GITHUB_TOKEN")
let repo = try getEnv("GITHUB_REPOSITORY")
let eventPath = try getEnv("GITHUB_EVENT_PATH")

guard let eventData = try String(contentsOfFile: eventPath).data(using: .utf8) else {
throw StringError("could not load event data at \(eventPath)")
}

let pullRequestEvent = try JSONDecoder().decode(PullRequestEvent.self, from: eventData)

let totalLinesChanged = pullRequestEvent.pull_request.additions + pullRequestEvent.pull_request.deletions
print("The pull has \(totalLinesChanged) changed lines")
let totalLinesChanged = pullRequestEvent.pull_request.additions +
pullRequestEvent.pull_request.deletions

print("The pull request has \(totalLinesChanged) changed lines")

let label: String
if totalLinesChanged < 10 {
label = "XS"
} else if totalLinesChanged < 100 {
label = "S"
} else if totalLinesChanged < 500 {
label = "M"
} else if totalLinesChanged < 1000 {
label = "L"
if try totalLinesChanged < getInputEnv("PR_SIZE_XS_LIMIT", defaultValue: 10) {
label = try getInputEnv("PR_SIZE_XS_LABEL", defaultValue: "XS")
} else if try totalLinesChanged < getInputEnv("PR_SIZE_S_LIMIT", defaultValue: 100) {
label = try getInputEnv("PR_SIZE_S_LABEL", defaultValue: "S")
} else if try totalLinesChanged < getInputEnv("PR_SIZE_M_LIMIT", defaultValue: 500) {
label = try getInputEnv("PR_SIZE_M_LABEL", defaultValue: "M")
} else if try totalLinesChanged < getInputEnv("PR_SIZE_L_LIMIT", defaultValue: 1000) {
label = try getInputEnv("PR_SIZE_L_LABEL", defaultValue: "L")
} else {
label = "XL"
label = try getInputEnv("PR_SIZE_XL_LABEL", defaultValue: "XL")
}

print("Assigning the \(label) label")
print("Assigning the \(label) label to pull request #\(pullRequestEvent.number)")

let provider = APIProvider(configuration: GithubConfiguration(token: githubToken))

let body = LabelsChangeRequest(labels: [label])
try await provider.request(
.setLabels(repo: repo, pullRequestID: pullRequestEvent.number),
body: body
body: LabelsChangeRequest(labels: [label])
)
}

private func getEnv(key: String) throws -> String {
guard let value = ProcessInfo.processInfo.environment[key] else {
throw StringError("\(key) environment variable not set")
}

return value
}
}
7 changes: 6 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
name: Copilot Swift PR Actions
description: Collection of PR Actions geared mostly towards iOS projects

inputs:
action_name:
description: 'Which action should be invoked'
required: true
runs:
using: docker
image: Dockerfile
args:
- ${{ inputs.action_name }}

0 comments on commit dca1c36

Please sign in to comment.