Skip to content

Instantly share code, notes, and snippets.

@bronumski
Last active December 30, 2015 03:59
Show Gist options
  • Save bronumski/7773030 to your computer and use it in GitHub Desktop.
Save bronumski/7773030 to your computer and use it in GitHub Desktop.
FSharp script to import into YouTrack from a CSV file
module Constants =
[<Literal>]
let ImportDataFileUrl = "Data.csv"
let YouTrackUrl = "http://LocalHost:8082"
let YouTrackAdminUserName = "root"
let YouTrackAdminPassword = "password"
let YouTrackProjectID = "PROJ"
#r "FSharp.Data.1.1.10/lib/net40/FSharp.Data.dll"
#r "RestSharp.104.4.0/lib/net4/RestSharp.dll"
open System.Xml.Serialization
open FSharp.Data
open RestSharp
type ImportIssue = CsvProvider<Constants.ImportDataFileUrl>
let getCurrentTicks(importedIssue : ImportIssue.Row) =
System.DateTime.Now.Ticks.ToString()
let mappings =
[ //YOUTRACK FIELD NAME TYPE CARDINALITY REQUIRED DESCRIPTION
"numberInProject", fun (issue : ImportIssue.Row) -> issue.Number.ToString(); // long single YES Issue number in project. Should be unique
"summary", fun issue -> issue.Name; // string single YES Issue summary
"description", fun issue -> issue.Description; // string single NO Full issue description
"created", getCurrentTicks; // UNIX Epoch timestamp single YES Issue creation time
"updated", fun issue -> null; // UNIX Epoch timestamp single NO Last issue update time
"updaterName", fun issue -> null; // string single NO Login name of last issue updater
"resolved", fun issue -> null; // UNIX Epoch timestamp single NO Issue resolve time
"reporterName", fun issue -> "root"; // string single NO Login name of issue reporter
"voterName", fun issue -> null; // string multi NO Login names of users who voted for the issue.
"watcherName", fun issue -> null; // string multi NO Login names of users who enabled watching issue changes.
"permittedGroup", fun issue -> null; // string single NO Name of group that has an access to the issue. See GET Groups
]
type Field(fieldName, fieldValue) =
[<XmlAttribute("name")>] member val FieldName = fieldName with get, set
[<XmlElement("value")>] member val FieldValue = fieldValue with get, set
public new() = Field("","")
type Issue(fields: Field[]) =
[<XmlElement "field">] member val Fields = fields with get, set
public new() = Issue([||])
[<XmlRoot("issues")>]
type YoutrackIssues(issues: Issue[]) =
[<XmlElement("issue")>] member val Issues = issues with get, set
public new() = YoutrackIssues([||])
let mapImportedIssue (issueToMap : ImportIssue.Row) fieldMappings =
let myMappedFields = fieldMappings |> Seq.choose (function | name, value when value(issueToMap) <> null -> Some(Field(name, value(issueToMap))) | _ -> None)
new Issue(Seq.toArray(myMappedFields))
let importedIssues = ImportIssue.Load Constants.ImportDataFileUrl
let mapImportedIssues (issuesToMap : ImportIssue.Row seq) fieldMappings =
issuesToMap |> Seq.map ( fun row -> mapImportedIssue row fieldMappings )
let mappedIssues = YoutrackIssues(Seq.toArray(mapImportedIssues importedIssues.Data mappings))
let youtrackClient url =
let client = RestClient url
client.CookieContainer <- new System.Net.CookieContainer()
client
let yClient = youtrackClient Constants.YouTrackUrl
let signIn (client : RestClient) login password =
let request = RestRequest("rest/user/login", Method.POST)
.AddParameter("login", login, ParameterType.GetOrPost)
.AddParameter("password", password, ParameterType.GetOrPost)
client.Execute request
let sendIssue (client : RestClient) projectId issues =
let importUrl = sprintf "rest/import/%s/issues" projectId
let request = RestRequest(importUrl, Method.PUT)
request.RequestFormat <- RestSharp.DataFormat.Xml;
request.XmlSerializer <- RestSharp.Serializers.DotNetXmlSerializer();
request.AddBody(issues) |> client.Execute
let LogFileName = sprintf @"YouTrackImportLog%s.txt" (System.DateTime.Now.ToString("yyyyMMdd-HHmmss"))
printf "%A" LogFileName
let writeLog(message : string) =
let currentTime = System.DateTime.Now.ToString()
use outp = System.IO.File.AppendText(LogFileName) in
(outp.WriteLine(sprintf "%s - %s" currentTime message))
let LogResponse(response : IRestResponse) =
writeLog(sprintf "Status Code '%s'\r\nResponse:\r\n%s" (response.StatusCode.ToString()) response.Content)
writeLog("Starting import run")
let signInResponse = signIn yClient Constants.YouTrackAdminUserName Constants.YouTrackAdminPassword
LogResponse signInResponse
let importResponse = sendIssue yClient Constants.YouTrackProjectID mappedIssues
LogResponse importResponse
writeLog("Import run complete")
System.Diagnostics.Process.Start(LogFileName);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment