1module Concourse exposing 2 ( AuthSession 3 , AuthToken 4 , Build 5 , BuildDuration 6 , BuildId 7 , BuildName 8 , BuildPlan 9 , BuildPrep 10 , BuildPrepStatus(..) 11 , BuildResources 12 , BuildResourcesInput 13 , BuildResourcesOutput 14 , BuildStep(..) 15 , CSRFToken 16 , Cause 17 , Check 18 , CheckIdentifier 19 , CheckStatus(..) 20 , ClusterInfo 21 , DatabaseID 22 , HookedPlan 23 , Job 24 , JobBuildIdentifier 25 , JobIdentifier 26 , JobInput 27 , JobName 28 , JobOutput 29 , JsonValue(..) 30 , Metadata 31 , MetadataField 32 , Pipeline 33 , PipelineGroup 34 , PipelineIdentifier 35 , PipelineName 36 , Resource 37 , ResourceIdentifier 38 , Team 39 , TeamName 40 , User 41 , Version 42 , VersionedResource 43 , VersionedResourceIdentifier 44 , csrfTokenHeaderName 45 , customDecoder 46 , decodeAuthToken 47 , decodeBuild 48 , decodeBuildPlan 49 , decodeBuildPrep 50 , decodeBuildResources 51 , decodeCause 52 , decodeCheck 53 , decodeInfo 54 , decodeJob 55 , decodeMetadata 56 , decodePipeline 57 , decodeResource 58 , decodeTeam 59 , decodeUser 60 , decodeVersion 61 , decodeVersionedResource 62 , emptyBuildResources 63 , encodeBuild 64 , encodeJob 65 , encodePipeline 66 , encodeTeam 67 , mapBuildPlan 68 , retrieveCSRFToken 69 ) 70 71import Array exposing (Array) 72import Concourse.BuildStatus exposing (BuildStatus) 73import Dict exposing (Dict) 74import Json.Decode 75import Json.Decode.Extra exposing (andMap) 76import Json.Encode 77import Json.Encode.Extra 78import Time 79 80 81 82-- AuthToken 83 84 85type alias AuthToken = 86 String 87 88 89type alias DatabaseID = 90 Int 91 92 93decodeAuthToken : Json.Decode.Decoder AuthToken 94decodeAuthToken = 95 customDecoder 96 (Json.Decode.succeed (\a b -> ( a, b )) 97 |> andMap (Json.Decode.field "type" Json.Decode.string) 98 |> andMap (Json.Decode.field "value" Json.Decode.string) 99 ) 100 authTokenFromTuple 101 102 103authTokenFromTuple : ( String, String ) -> Result Json.Decode.Error AuthToken 104authTokenFromTuple ( t, token ) = 105 case t of 106 "Bearer" -> 107 Ok token 108 109 _ -> 110 Err <| Json.Decode.Failure "unknown token type" <| Json.Encode.string token 111 112 113 114-- CSRF token 115 116 117type alias CSRFToken = 118 String 119 120 121csrfTokenHeaderName : String 122csrfTokenHeaderName = 123 "X-Csrf-Token" 124 125 126retrieveCSRFToken : Dict String String -> Result String CSRFToken 127retrieveCSRFToken headers = 128 Dict.get (String.toLower csrfTokenHeaderName) (keysToLower headers) |> Result.fromMaybe "error CSRFToken not found" 129 130 131keysToLower : Dict String a -> Dict String a 132keysToLower = 133 Dict.fromList << List.map fstToLower << Dict.toList 134 135 136fstToLower : ( String, a ) -> ( String, a ) 137fstToLower ( x, y ) = 138 ( String.toLower x, y ) 139 140 141type alias AuthSession = 142 { authToken : AuthToken 143 , csrfToken : CSRFToken 144 } 145 146 147 148-- Build 149 150 151type alias BuildId = 152 Int 153 154 155type alias BuildName = 156 String 157 158 159type alias JobBuildIdentifier = 160 { teamName : TeamName 161 , pipelineName : PipelineName 162 , jobName : JobName 163 , buildName : BuildName 164 } 165 166 167type alias Build = 168 { id : BuildId 169 , name : BuildName 170 , job : Maybe JobIdentifier 171 , status : BuildStatus 172 , duration : BuildDuration 173 , reapTime : Maybe Time.Posix 174 } 175 176 177type alias BuildDuration = 178 { startedAt : Maybe Time.Posix 179 , finishedAt : Maybe Time.Posix 180 } 181 182 183encodeBuild : Build -> Json.Encode.Value 184encodeBuild build = 185 Json.Encode.object 186 ([ ( "id", build.id |> Json.Encode.int ) |> Just 187 , ( "name", build.name |> Json.Encode.string ) |> Just 188 , optionalField "team_name" Json.Encode.string (build.job |> Maybe.map .teamName) 189 , optionalField "pipeline_name" Json.Encode.string (build.job |> Maybe.map .pipelineName) 190 , optionalField "job_name" Json.Encode.string (build.job |> Maybe.map .jobName) 191 , ( "status", build.status |> Concourse.BuildStatus.encodeBuildStatus ) |> Just 192 , optionalField "start_time" (secondsFromDate >> Json.Encode.int) build.duration.startedAt 193 , optionalField "end_time" (secondsFromDate >> Json.Encode.int) build.duration.finishedAt 194 , optionalField "reap_time" (secondsFromDate >> Json.Encode.int) build.reapTime 195 ] 196 |> List.filterMap identity 197 ) 198 199 200encodeMaybeBuild : Maybe Build -> Json.Encode.Value 201encodeMaybeBuild maybeBuild = 202 case maybeBuild of 203 Nothing -> 204 Json.Encode.null 205 206 Just build -> 207 encodeBuild build 208 209 210decodeBuild : Json.Decode.Decoder Build 211decodeBuild = 212 Json.Decode.succeed Build 213 |> andMap (Json.Decode.field "id" Json.Decode.int) 214 |> andMap (Json.Decode.field "name" Json.Decode.string) 215 |> andMap 216 (Json.Decode.maybe 217 (Json.Decode.succeed JobIdentifier 218 |> andMap (Json.Decode.field "team_name" Json.Decode.string) 219 |> andMap (Json.Decode.field "pipeline_name" Json.Decode.string) 220 |> andMap (Json.Decode.field "job_name" Json.Decode.string) 221 ) 222 ) 223 |> andMap (Json.Decode.field "status" Concourse.BuildStatus.decodeBuildStatus) 224 |> andMap 225 (Json.Decode.succeed BuildDuration 226 |> andMap (Json.Decode.maybe (Json.Decode.field "start_time" (Json.Decode.map dateFromSeconds Json.Decode.int))) 227 |> andMap (Json.Decode.maybe (Json.Decode.field "end_time" (Json.Decode.map dateFromSeconds Json.Decode.int))) 228 ) 229 |> andMap (Json.Decode.maybe (Json.Decode.field "reap_time" (Json.Decode.map dateFromSeconds Json.Decode.int))) 230 231 232 233-- BuildPrep 234 235 236type alias BuildPrep = 237 { pausedPipeline : BuildPrepStatus 238 , pausedJob : BuildPrepStatus 239 , maxRunningBuilds : BuildPrepStatus 240 , inputs : Dict String BuildPrepStatus 241 , inputsSatisfied : BuildPrepStatus 242 , missingInputReasons : Dict String String 243 } 244 245 246type BuildPrepStatus 247 = BuildPrepStatusUnknown 248 | BuildPrepStatusBlocking 249 | BuildPrepStatusNotBlocking 250 251 252decodeBuildPrep : Json.Decode.Decoder BuildPrep 253decodeBuildPrep = 254 Json.Decode.succeed BuildPrep 255 |> andMap (Json.Decode.field "paused_pipeline" decodeBuildPrepStatus) 256 |> andMap (Json.Decode.field "paused_job" decodeBuildPrepStatus) 257 |> andMap (Json.Decode.field "max_running_builds" decodeBuildPrepStatus) 258 |> andMap (Json.Decode.field "inputs" <| Json.Decode.dict decodeBuildPrepStatus) 259 |> andMap (Json.Decode.field "inputs_satisfied" decodeBuildPrepStatus) 260 |> andMap (defaultTo Dict.empty <| Json.Decode.field "missing_input_reasons" <| Json.Decode.dict Json.Decode.string) 261 262 263decodeBuildPrepStatus : Json.Decode.Decoder BuildPrepStatus 264decodeBuildPrepStatus = 265 customDecoder Json.Decode.string <| 266 \status -> 267 case status of 268 "unknown" -> 269 Ok BuildPrepStatusUnknown 270 271 "blocking" -> 272 Ok BuildPrepStatusBlocking 273 274 "not_blocking" -> 275 Ok BuildPrepStatusNotBlocking 276 277 unknown -> 278 Err <| Json.Decode.Failure "unknown build preparation status" <| Json.Encode.string unknown 279 280 281 282-- BuildResources 283 284 285type alias BuildResources = 286 { inputs : List BuildResourcesInput 287 , outputs : List BuildResourcesOutput 288 } 289 290 291type alias BuildResourcesInput = 292 { name : String 293 , version : Version 294 , firstOccurrence : Bool 295 } 296 297 298type alias BuildResourcesOutput = 299 { name : String 300 , version : Version 301 } 302 303 304emptyBuildResources : BuildResources 305emptyBuildResources = 306 { inputs = [] 307 , outputs = [] 308 } 309 310 311decodeBuildResources : Json.Decode.Decoder BuildResources 312decodeBuildResources = 313 Json.Decode.succeed BuildResources 314 |> andMap (Json.Decode.field "inputs" <| Json.Decode.list decodeResourcesInput) 315 |> andMap (Json.Decode.field "outputs" <| Json.Decode.list decodeResourcesOutput) 316 317 318decodeResourcesInput : Json.Decode.Decoder BuildResourcesInput 319decodeResourcesInput = 320 Json.Decode.succeed BuildResourcesInput 321 |> andMap (Json.Decode.field "name" Json.Decode.string) 322 |> andMap (Json.Decode.field "version" decodeVersion) 323 |> andMap (Json.Decode.field "first_occurrence" Json.Decode.bool) 324 325 326decodeResourcesOutput : Json.Decode.Decoder BuildResourcesOutput 327decodeResourcesOutput = 328 Json.Decode.succeed BuildResourcesOutput 329 |> andMap (Json.Decode.field "name" Json.Decode.string) 330 |> andMap (Json.Decode.field "version" <| Json.Decode.dict Json.Decode.string) 331 332 333 334-- BuildPlan 335 336 337type alias BuildPlan = 338 { id : String 339 , step : BuildStep 340 } 341 342 343mapBuildPlan : (BuildPlan -> a) -> BuildPlan -> List a 344mapBuildPlan fn plan = 345 fn plan 346 :: (case plan.step of 347 BuildStepTask _ -> 348 [] 349 350 BuildStepSetPipeline _ -> 351 [] 352 353 BuildStepLoadVar _ -> 354 [] 355 356 BuildStepArtifactInput _ -> 357 [] 358 359 BuildStepPut _ -> 360 [] 361 362 BuildStepGet _ _ -> 363 [] 364 365 BuildStepArtifactOutput _ -> 366 [] 367 368 BuildStepAggregate plans -> 369 List.concatMap (mapBuildPlan fn) (Array.toList plans) 370 371 BuildStepInParallel plans -> 372 List.concatMap (mapBuildPlan fn) (Array.toList plans) 373 374 BuildStepAcross { steps } -> 375 List.concatMap (mapBuildPlan fn) 376 (steps |> List.map Tuple.second) 377 378 BuildStepDo plans -> 379 List.concatMap (mapBuildPlan fn) (Array.toList plans) 380 381 BuildStepOnSuccess { step, hook } -> 382 mapBuildPlan fn step ++ mapBuildPlan fn hook 383 384 BuildStepOnFailure { step, hook } -> 385 mapBuildPlan fn step ++ mapBuildPlan fn hook 386 387 BuildStepOnAbort { step, hook } -> 388 mapBuildPlan fn step ++ mapBuildPlan fn hook 389 390 BuildStepOnError { step, hook } -> 391 mapBuildPlan fn step ++ mapBuildPlan fn hook 392 393 BuildStepEnsure { step, hook } -> 394 mapBuildPlan fn step ++ mapBuildPlan fn hook 395 396 BuildStepTry step -> 397 mapBuildPlan fn step 398 399 BuildStepRetry plans -> 400 List.concatMap (mapBuildPlan fn) (Array.toList plans) 401 402 BuildStepTimeout step -> 403 mapBuildPlan fn step 404 ) 405 406 407type alias StepName = 408 String 409 410 411type BuildStep 412 = BuildStepTask StepName 413 | BuildStepSetPipeline StepName 414 | BuildStepLoadVar StepName 415 | BuildStepArtifactInput StepName 416 | BuildStepGet StepName (Maybe Version) 417 | BuildStepArtifactOutput StepName 418 | BuildStepPut StepName 419 | BuildStepAggregate (Array BuildPlan) 420 | BuildStepInParallel (Array BuildPlan) 421 | BuildStepAcross AcrossPlan 422 | BuildStepDo (Array BuildPlan) 423 | BuildStepOnSuccess HookedPlan 424 | BuildStepOnFailure HookedPlan 425 | BuildStepOnAbort HookedPlan 426 | BuildStepOnError HookedPlan 427 | BuildStepEnsure HookedPlan 428 | BuildStepTry BuildPlan 429 | BuildStepRetry (Array BuildPlan) 430 | BuildStepTimeout BuildPlan 431 432 433type alias HookedPlan = 434 { step : BuildPlan 435 , hook : BuildPlan 436 } 437 438 439type JsonValue 440 = JsonString String 441 | JsonNumber Float 442 | JsonObject (List ( String, JsonValue )) 443 | JsonArray (List JsonValue) 444 | JsonRaw Json.Decode.Value 445 446 447decodeJsonValue : Json.Decode.Decoder JsonValue 448decodeJsonValue = 449 Json.Decode.oneOf 450 [ Json.Decode.keyValuePairs decodeSimpleJsonValue |> Json.Decode.map JsonObject 451 , Json.Decode.list decodeSimpleJsonValue |> Json.Decode.map JsonArray 452 , decodeSimpleJsonValue 453 ] 454 455 456decodeSimpleJsonValue : Json.Decode.Decoder JsonValue 457decodeSimpleJsonValue = 458 Json.Decode.oneOf 459 [ Json.Decode.string |> Json.Decode.map JsonString 460 , Json.Decode.float |> Json.Decode.map JsonNumber 461 , Json.Decode.value |> Json.Decode.map JsonRaw 462 ] 463 464 465type alias AcrossPlan = 466 { vars : List String 467 , steps : List ( List JsonValue, BuildPlan ) 468 } 469 470 471decodeBuildPlan : Json.Decode.Decoder BuildPlan 472decodeBuildPlan = 473 Json.Decode.at [ "plan" ] <| 474 decodeBuildPlan_ 475 476 477decodeBuildPlan_ : Json.Decode.Decoder BuildPlan 478decodeBuildPlan_ = 479 Json.Decode.succeed BuildPlan 480 |> andMap (Json.Decode.field "id" Json.Decode.string) 481 |> andMap 482 (Json.Decode.oneOf 483 -- buckle up 484 [ Json.Decode.field "task" <| 485 lazy (\_ -> decodeBuildStepTask) 486 , Json.Decode.field "get" <| 487 lazy (\_ -> decodeBuildStepGet) 488 , Json.Decode.field "artifact_input" <| 489 lazy (\_ -> decodeBuildStepArtifactInput) 490 , Json.Decode.field "put" <| 491 lazy (\_ -> decodeBuildStepPut) 492 , Json.Decode.field "artifact_output" <| 493 lazy (\_ -> decodeBuildStepArtifactOutput) 494 , Json.Decode.field "dependent_get" <| 495 lazy (\_ -> decodeBuildStepGet) 496 , Json.Decode.field "aggregate" <| 497 lazy (\_ -> decodeBuildStepAggregate) 498 , Json.Decode.field "in_parallel" <| 499 lazy (\_ -> decodeBuildStepInParallel) 500 , Json.Decode.field "do" <| 501 lazy (\_ -> decodeBuildStepDo) 502 , Json.Decode.field "on_success" <| 503 lazy (\_ -> decodeBuildStepOnSuccess) 504 , Json.Decode.field "on_failure" <| 505 lazy (\_ -> decodeBuildStepOnFailure) 506 , Json.Decode.field "on_abort" <| 507 lazy (\_ -> decodeBuildStepOnAbort) 508 , Json.Decode.field "on_error" <| 509 lazy (\_ -> decodeBuildStepOnError) 510 , Json.Decode.field "ensure" <| 511 lazy (\_ -> decodeBuildStepEnsure) 512 , Json.Decode.field "try" <| 513 lazy (\_ -> decodeBuildStepTry) 514 , Json.Decode.field "retry" <| 515 lazy (\_ -> decodeBuildStepRetry) 516 , Json.Decode.field "timeout" <| 517 lazy (\_ -> decodeBuildStepTimeout) 518 , Json.Decode.field "set_pipeline" <| 519 lazy (\_ -> decodeBuildSetPipeline) 520 , Json.Decode.field "load_var" <| 521 lazy (\_ -> decodeBuildStepLoadVar) 522 , Json.Decode.field "across" <| 523 lazy (\_ -> decodeBuildStepAcross) 524 ] 525 ) 526 527 528decodeBuildStepTask : Json.Decode.Decoder BuildStep 529decodeBuildStepTask = 530 Json.Decode.succeed BuildStepTask 531 |> andMap (Json.Decode.field "name" Json.Decode.string) 532 533 534decodeBuildStepArtifactInput : Json.Decode.Decoder BuildStep 535decodeBuildStepArtifactInput = 536 Json.Decode.succeed BuildStepArtifactInput 537 |> andMap (Json.Decode.field "name" Json.Decode.string) 538 539 540decodeBuildStepGet : Json.Decode.Decoder BuildStep 541decodeBuildStepGet = 542 Json.Decode.succeed BuildStepGet 543 |> andMap (Json.Decode.field "name" Json.Decode.string) 544 |> andMap (Json.Decode.maybe <| Json.Decode.field "version" decodeVersion) 545 546 547decodeBuildStepArtifactOutput : Json.Decode.Decoder BuildStep 548decodeBuildStepArtifactOutput = 549 Json.Decode.succeed BuildStepArtifactOutput 550 |> andMap (Json.Decode.field "name" Json.Decode.string) 551 552 553decodeBuildStepPut : Json.Decode.Decoder BuildStep 554decodeBuildStepPut = 555 Json.Decode.succeed BuildStepPut 556 |> andMap (Json.Decode.field "name" Json.Decode.string) 557 558 559decodeBuildStepAggregate : Json.Decode.Decoder BuildStep 560decodeBuildStepAggregate = 561 Json.Decode.succeed BuildStepAggregate 562 |> andMap (Json.Decode.array (lazy (\_ -> decodeBuildPlan_))) 563 564 565decodeBuildStepInParallel : Json.Decode.Decoder BuildStep 566decodeBuildStepInParallel = 567 Json.Decode.succeed BuildStepInParallel 568 |> andMap (Json.Decode.field "steps" <| Json.Decode.array (lazy (\_ -> decodeBuildPlan_))) 569 570 571decodeBuildStepDo : Json.Decode.Decoder BuildStep 572decodeBuildStepDo = 573 Json.Decode.succeed BuildStepDo 574 |> andMap (Json.Decode.array (lazy (\_ -> decodeBuildPlan_))) 575 576 577decodeBuildStepOnSuccess : Json.Decode.Decoder BuildStep 578decodeBuildStepOnSuccess = 579 Json.Decode.map BuildStepOnSuccess 580 (Json.Decode.succeed HookedPlan 581 |> andMap (Json.Decode.field "step" <| lazy (\_ -> decodeBuildPlan_)) 582 |> andMap (Json.Decode.field "on_success" <| lazy (\_ -> decodeBuildPlan_)) 583 ) 584 585 586decodeBuildStepOnFailure : Json.Decode.Decoder BuildStep 587decodeBuildStepOnFailure = 588 Json.Decode.map BuildStepOnFailure 589 (Json.Decode.succeed HookedPlan 590 |> andMap (Json.Decode.field "step" <| lazy (\_ -> decodeBuildPlan_)) 591 |> andMap (Json.Decode.field "on_failure" <| lazy (\_ -> decodeBuildPlan_)) 592 ) 593 594 595decodeBuildStepOnAbort : Json.Decode.Decoder BuildStep 596decodeBuildStepOnAbort = 597 Json.Decode.map BuildStepOnAbort 598 (Json.Decode.succeed HookedPlan 599 |> andMap (Json.Decode.field "step" <| lazy (\_ -> decodeBuildPlan_)) 600 |> andMap (Json.Decode.field "on_abort" <| lazy (\_ -> decodeBuildPlan_)) 601 ) 602 603 604decodeBuildStepOnError : Json.Decode.Decoder BuildStep 605decodeBuildStepOnError = 606 Json.Decode.map BuildStepOnError 607 (Json.Decode.succeed HookedPlan 608 |> andMap (Json.Decode.field "step" <| lazy (\_ -> decodeBuildPlan_)) 609 |> andMap (Json.Decode.field "on_error" <| lazy (\_ -> decodeBuildPlan_)) 610 ) 611 612 613decodeBuildStepEnsure : Json.Decode.Decoder BuildStep 614decodeBuildStepEnsure = 615 Json.Decode.map BuildStepEnsure 616 (Json.Decode.succeed HookedPlan 617 |> andMap (Json.Decode.field "step" <| lazy (\_ -> decodeBuildPlan_)) 618 |> andMap (Json.Decode.field "ensure" <| lazy (\_ -> decodeBuildPlan_)) 619 ) 620 621 622decodeBuildStepTry : Json.Decode.Decoder BuildStep 623decodeBuildStepTry = 624 Json.Decode.succeed BuildStepTry 625 |> andMap (Json.Decode.field "step" <| lazy (\_ -> decodeBuildPlan_)) 626 627 628decodeBuildStepRetry : Json.Decode.Decoder BuildStep 629decodeBuildStepRetry = 630 Json.Decode.succeed BuildStepRetry 631 |> andMap (Json.Decode.array (lazy (\_ -> decodeBuildPlan_))) 632 633 634decodeBuildStepTimeout : Json.Decode.Decoder BuildStep 635decodeBuildStepTimeout = 636 Json.Decode.succeed BuildStepTimeout 637 |> andMap (Json.Decode.field "step" <| lazy (\_ -> decodeBuildPlan_)) 638 639 640decodeBuildSetPipeline : Json.Decode.Decoder BuildStep 641decodeBuildSetPipeline = 642 Json.Decode.succeed BuildStepSetPipeline 643 |> andMap (Json.Decode.field "name" Json.Decode.string) 644 645 646decodeBuildStepLoadVar : Json.Decode.Decoder BuildStep 647decodeBuildStepLoadVar = 648 Json.Decode.succeed BuildStepLoadVar 649 |> andMap (Json.Decode.field "name" Json.Decode.string) 650 651 652decodeBuildStepAcross : Json.Decode.Decoder BuildStep 653decodeBuildStepAcross = 654 Json.Decode.map BuildStepAcross 655 (Json.Decode.succeed AcrossPlan 656 |> andMap 657 (Json.Decode.field "vars" <| 658 Json.Decode.list <| 659 Json.Decode.field "name" Json.Decode.string 660 ) 661 |> andMap 662 (Json.Decode.field "steps" <| 663 Json.Decode.list <| 664 Json.Decode.map2 Tuple.pair 665 (Json.Decode.field "values" <| Json.Decode.list decodeJsonValue) 666 (Json.Decode.field "step" decodeBuildPlan_) 667 ) 668 ) 669 670 671 672-- Info 673 674 675type alias ClusterInfo = 676 { version : String 677 , clusterName : String 678 } 679 680 681decodeInfo : Json.Decode.Decoder ClusterInfo 682decodeInfo = 683 Json.Decode.succeed ClusterInfo 684 |> andMap (Json.Decode.field "version" Json.Decode.string) 685 |> andMap (defaultTo "" <| Json.Decode.field "cluster_name" Json.Decode.string) 686 687 688 689-- Job 690 691 692type alias JobName = 693 String 694 695 696type alias JobIdentifier = 697 { teamName : TeamName 698 , pipelineName : PipelineName 699 , jobName : JobName 700 } 701 702 703type alias Job = 704 { name : JobName 705 , pipelineName : PipelineName 706 , teamName : TeamName 707 , nextBuild : Maybe Build 708 , finishedBuild : Maybe Build 709 , transitionBuild : Maybe Build 710 , paused : Bool 711 , disableManualTrigger : Bool 712 , inputs : List JobInput 713 , outputs : List JobOutput 714 , groups : List String 715 } 716 717 718type alias JobInput = 719 { name : String 720 , resource : String 721 , passed : List String 722 , trigger : Bool 723 } 724 725 726type alias JobOutput = 727 { name : String 728 , resource : String 729 } 730 731 732encodeJob : Job -> Json.Encode.Value 733encodeJob job = 734 Json.Encode.object 735 [ ( "name", job.name |> Json.Encode.string ) 736 , ( "pipeline_name", job.pipelineName |> Json.Encode.string ) 737 , ( "team_name", job.teamName |> Json.Encode.string ) 738 , ( "next_build", job.nextBuild |> encodeMaybeBuild ) 739 , ( "finished_build", job.finishedBuild |> encodeMaybeBuild ) 740 , ( "transition_build", job.finishedBuild |> encodeMaybeBuild ) 741 , ( "paused", job.paused |> Json.Encode.bool ) 742 , ( "disable_manual_trigger", job.paused |> Json.Encode.bool ) 743 , ( "disable_manual_trigger", job.disableManualTrigger |> Json.Encode.bool ) 744 , ( "inputs", job.inputs |> Json.Encode.list encodeJobInput ) 745 , ( "outputs", job.outputs |> Json.Encode.list encodeJobOutput ) 746 , ( "groups", job.groups |> Json.Encode.list Json.Encode.string ) 747 ] 748 749 750decodeJob : Json.Decode.Decoder Job 751decodeJob = 752 Json.Decode.succeed Job 753 |> andMap (Json.Decode.field "name" Json.Decode.string) 754 |> andMap (Json.Decode.field "pipeline_name" Json.Decode.string) 755 |> andMap (Json.Decode.field "team_name" Json.Decode.string) 756 |> andMap (Json.Decode.maybe (Json.Decode.field "next_build" decodeBuild)) 757 |> andMap (Json.Decode.maybe (Json.Decode.field "finished_build" decodeBuild)) 758 |> andMap (Json.Decode.maybe (Json.Decode.field "transition_build" decodeBuild)) 759 |> andMap (defaultTo False <| Json.Decode.field "paused" Json.Decode.bool) 760 |> andMap (defaultTo False <| Json.Decode.field "disable_manual_trigger" Json.Decode.bool) 761 |> andMap (defaultTo [] <| Json.Decode.field "inputs" <| Json.Decode.list decodeJobInput) 762 |> andMap (defaultTo [] <| Json.Decode.field "outputs" <| Json.Decode.list decodeJobOutput) 763 |> andMap (defaultTo [] <| Json.Decode.field "groups" <| Json.Decode.list Json.Decode.string) 764 765 766encodeJobInput : JobInput -> Json.Encode.Value 767encodeJobInput jobInput = 768 Json.Encode.object 769 [ ( "name", jobInput.name |> Json.Encode.string ) 770 , ( "resource", jobInput.resource |> Json.Encode.string ) 771 , ( "passed", jobInput.passed |> Json.Encode.list Json.Encode.string ) 772 , ( "trigger", jobInput.trigger |> Json.Encode.bool ) 773 ] 774 775 776decodeJobInput : Json.Decode.Decoder JobInput 777decodeJobInput = 778 Json.Decode.succeed JobInput 779 |> andMap (Json.Decode.field "name" Json.Decode.string) 780 |> andMap (Json.Decode.field "resource" Json.Decode.string) 781 |> andMap (defaultTo [] <| Json.Decode.field "passed" <| Json.Decode.list Json.Decode.string) 782 |> andMap (defaultTo False <| Json.Decode.field "trigger" Json.Decode.bool) 783 784 785encodeJobOutput : JobOutput -> Json.Encode.Value 786encodeJobOutput jobOutput = 787 Json.Encode.object 788 [ ( "name", jobOutput.name |> Json.Encode.string ) 789 , ( "resource", jobOutput.resource |> Json.Encode.string ) 790 ] 791 792 793decodeJobOutput : Json.Decode.Decoder JobOutput 794decodeJobOutput = 795 Json.Decode.succeed JobOutput 796 |> andMap (Json.Decode.field "name" Json.Decode.string) 797 |> andMap (Json.Decode.field "resource" Json.Decode.string) 798 799 800 801-- Pipeline 802 803 804type alias PipelineName = 805 String 806 807 808type alias PipelineIdentifier = 809 { teamName : TeamName 810 , pipelineName : PipelineName 811 } 812 813 814type alias Pipeline = 815 { id : Int 816 , name : PipelineName 817 , paused : Bool 818 , archived : Bool 819 , public : Bool 820 , teamName : TeamName 821 , groups : List PipelineGroup 822 , backgroundImage : Maybe String 823 } 824 825 826type alias PipelineGroup = 827 { name : String 828 , jobs : List String 829 , resources : List String 830 } 831 832 833encodePipeline : Pipeline -> Json.Encode.Value 834encodePipeline pipeline = 835 Json.Encode.object 836 [ ( "id", pipeline.id |> Json.Encode.int ) 837 , ( "name", pipeline.name |> Json.Encode.string ) 838 , ( "paused", pipeline.paused |> Json.Encode.bool ) 839 , ( "archived", pipeline.archived |> Json.Encode.bool ) 840 , ( "public", pipeline.public |> Json.Encode.bool ) 841 , ( "team_name", pipeline.teamName |> Json.Encode.string ) 842 , ( "groups", pipeline.groups |> Json.Encode.list encodePipelineGroup ) 843 , ( "display", Json.Encode.object [ ( "background_image", pipeline.backgroundImage |> Json.Encode.Extra.maybe Json.Encode.string ) ] ) 844 ] 845 846 847decodePipeline : Json.Decode.Decoder Pipeline 848decodePipeline = 849 Json.Decode.succeed Pipeline 850 |> andMap (Json.Decode.field "id" Json.Decode.int) 851 |> andMap (Json.Decode.field "name" Json.Decode.string) 852 |> andMap (Json.Decode.field "paused" Json.Decode.bool) 853 |> andMap (Json.Decode.field "archived" Json.Decode.bool) 854 |> andMap (Json.Decode.field "public" Json.Decode.bool) 855 |> andMap (Json.Decode.field "team_name" Json.Decode.string) 856 |> andMap (defaultTo [] <| Json.Decode.field "groups" (Json.Decode.list decodePipelineGroup)) 857 |> andMap (Json.Decode.maybe (Json.Decode.at [ "display", "background_image" ] Json.Decode.string)) 858 859 860encodePipelineGroup : PipelineGroup -> Json.Encode.Value 861encodePipelineGroup pipelineGroup = 862 Json.Encode.object 863 [ ( "name", pipelineGroup.name |> Json.Encode.string ) 864 , ( "jobs", pipelineGroup.jobs |> Json.Encode.list Json.Encode.string ) 865 , ( "resources", pipelineGroup.resources |> Json.Encode.list Json.Encode.string ) 866 ] 867 868 869decodePipelineGroup : Json.Decode.Decoder PipelineGroup 870decodePipelineGroup = 871 Json.Decode.succeed PipelineGroup 872 |> andMap (Json.Decode.field "name" Json.Decode.string) 873 |> andMap (defaultTo [] <| Json.Decode.field "jobs" <| Json.Decode.list Json.Decode.string) 874 |> andMap (defaultTo [] <| Json.Decode.field "resources" <| Json.Decode.list Json.Decode.string) 875 876 877 878-- Resource 879 880 881type alias Resource = 882 { teamName : String 883 , pipelineName : String 884 , name : String 885 , icon : Maybe String 886 , failingToCheck : Bool 887 , checkError : String 888 , checkSetupError : String 889 , lastChecked : Maybe Time.Posix 890 , pinnedVersion : Maybe Version 891 , pinnedInConfig : Bool 892 , pinComment : Maybe String 893 } 894 895 896type alias ResourceIdentifier = 897 { teamName : String 898 , pipelineName : String 899 , resourceName : String 900 } 901 902 903type alias CheckIdentifier = 904 { teamName : String 905 , pipelineName : String 906 , resourceName : String 907 , checkID : Int 908 } 909 910 911type alias VersionedResource = 912 { id : Int 913 , version : Version 914 , metadata : Metadata 915 , enabled : Bool 916 } 917 918 919type alias VersionedResourceIdentifier = 920 { teamName : String 921 , pipelineName : String 922 , resourceName : String 923 , versionID : Int 924 } 925 926 927type alias Check = 928 { id : Int 929 , status : CheckStatus 930 , createTime : Maybe Time.Posix 931 , startTime : Maybe Time.Posix 932 , endTime : Maybe Time.Posix 933 , checkError : Maybe String 934 } 935 936 937type CheckStatus 938 = Started 939 | Succeeded 940 | Errored 941 942 943decodeResource : Json.Decode.Decoder Resource 944decodeResource = 945 Json.Decode.succeed Resource 946 |> andMap (Json.Decode.field "team_name" Json.Decode.string) 947 |> andMap (Json.Decode.field "pipeline_name" Json.Decode.string) 948 |> andMap (Json.Decode.field "name" Json.Decode.string) 949 |> andMap (Json.Decode.maybe (Json.Decode.field "icon" Json.Decode.string)) 950 |> andMap (defaultTo False <| Json.Decode.field "failing_to_check" Json.Decode.bool) 951 |> andMap (defaultTo "" <| Json.Decode.field "check_error" Json.Decode.string) 952 |> andMap (defaultTo "" <| Json.Decode.field "check_setup_error" Json.Decode.string) 953 |> andMap (Json.Decode.maybe (Json.Decode.field "last_checked" (Json.Decode.map dateFromSeconds Json.Decode.int))) 954 |> andMap (Json.Decode.maybe (Json.Decode.field "pinned_version" decodeVersion)) 955 |> andMap (defaultTo False <| Json.Decode.field "pinned_in_config" Json.Decode.bool) 956 |> andMap (Json.Decode.maybe (Json.Decode.field "pin_comment" Json.Decode.string)) 957 958 959decodeVersionedResource : Json.Decode.Decoder VersionedResource 960decodeVersionedResource = 961 Json.Decode.succeed VersionedResource 962 |> andMap (Json.Decode.field "id" Json.Decode.int) 963 |> andMap (Json.Decode.field "version" decodeVersion) 964 |> andMap (defaultTo [] (Json.Decode.field "metadata" decodeMetadata)) 965 |> andMap (Json.Decode.field "enabled" Json.Decode.bool) 966 967 968decodeCheck : Json.Decode.Decoder Check 969decodeCheck = 970 Json.Decode.succeed Check 971 |> andMap (Json.Decode.field "id" Json.Decode.int) 972 |> andMap (Json.Decode.field "status" decodeCheckStatus) 973 |> andMap (Json.Decode.maybe (Json.Decode.field "create_time" (Json.Decode.map dateFromSeconds Json.Decode.int))) 974 |> andMap (Json.Decode.maybe (Json.Decode.field "start_time" (Json.Decode.map dateFromSeconds Json.Decode.int))) 975 |> andMap (Json.Decode.maybe (Json.Decode.field "end_time" (Json.Decode.map dateFromSeconds Json.Decode.int))) 976 |> andMap (Json.Decode.maybe (Json.Decode.field "check_error" Json.Decode.string)) 977 978 979decodeCheckStatus : Json.Decode.Decoder CheckStatus 980decodeCheckStatus = 981 Json.Decode.string 982 |> Json.Decode.andThen 983 (\status -> 984 case status of 985 "started" -> 986 Json.Decode.succeed Started 987 988 "succeeded" -> 989 Json.Decode.succeed Succeeded 990 991 "errored" -> 992 Json.Decode.succeed Errored 993 994 unknown -> 995 Json.Decode.fail <| "unknown check status: " ++ unknown 996 ) 997 998 999 1000-- Version 1001 1002 1003type alias Version = 1004 Dict String String 1005 1006 1007decodeVersion : Json.Decode.Decoder Version 1008decodeVersion = 1009 Json.Decode.dict Json.Decode.string 1010 1011 1012 1013-- Metadata 1014 1015 1016type alias Metadata = 1017 List MetadataField 1018 1019 1020type alias MetadataField = 1021 { name : String 1022 , value : String 1023 } 1024 1025 1026decodeMetadata : Json.Decode.Decoder (List MetadataField) 1027decodeMetadata = 1028 Json.Decode.list decodeMetadataField 1029 1030 1031decodeMetadataField : Json.Decode.Decoder MetadataField 1032decodeMetadataField = 1033 Json.Decode.succeed MetadataField 1034 |> andMap (Json.Decode.field "name" Json.Decode.string) 1035 |> andMap (Json.Decode.field "value" Json.Decode.string) 1036 1037 1038 1039-- Team 1040 1041 1042type alias TeamName = 1043 String 1044 1045 1046type alias Team = 1047 { id : Int 1048 , name : TeamName 1049 } 1050 1051 1052encodeTeam : Team -> Json.Encode.Value 1053encodeTeam team = 1054 Json.Encode.object 1055 [ ( "id", team.id |> Json.Encode.int ) 1056 , ( "name", team.name |> Json.Encode.string ) 1057 ] 1058 1059 1060decodeTeam : Json.Decode.Decoder Team 1061decodeTeam = 1062 Json.Decode.succeed Team 1063 |> andMap (Json.Decode.field "id" Json.Decode.int) 1064 |> andMap (Json.Decode.field "name" Json.Decode.string) 1065 1066 1067 1068-- User 1069 1070 1071type alias User = 1072 { id : String 1073 , userName : String 1074 , name : String 1075 , email : String 1076 , isAdmin : Bool 1077 , teams : Dict String (List String) 1078 } 1079 1080 1081decodeUser : Json.Decode.Decoder User 1082decodeUser = 1083 Json.Decode.succeed User 1084 |> andMap (Json.Decode.field "user_id" Json.Decode.string) 1085 |> andMap (Json.Decode.field "user_name" Json.Decode.string) 1086 |> andMap (Json.Decode.field "name" Json.Decode.string) 1087 |> andMap (Json.Decode.field "email" Json.Decode.string) 1088 |> andMap (Json.Decode.field "is_admin" Json.Decode.bool) 1089 |> andMap (Json.Decode.field "teams" (Json.Decode.dict (Json.Decode.list Json.Decode.string))) 1090 1091 1092 1093-- Cause 1094 1095 1096type alias Cause = 1097 { versionedResourceID : Int 1098 , buildID : Int 1099 } 1100 1101 1102decodeCause : Json.Decode.Decoder Cause 1103decodeCause = 1104 Json.Decode.succeed Cause 1105 |> andMap (Json.Decode.field "versioned_resource_id" Json.Decode.int) 1106 |> andMap (Json.Decode.field "build_id" Json.Decode.int) 1107 1108 1109 1110-- Helpers 1111 1112 1113dateFromSeconds : Int -> Time.Posix 1114dateFromSeconds = 1115 Time.millisToPosix << (*) 1000 1116 1117 1118secondsFromDate : Time.Posix -> Int 1119secondsFromDate = 1120 Time.posixToMillis >> (\m -> m // 1000) 1121 1122 1123lazy : (() -> Json.Decode.Decoder a) -> Json.Decode.Decoder a 1124lazy thunk = 1125 customDecoder Json.Decode.value 1126 (\js -> Json.Decode.decodeValue (thunk ()) js) 1127 1128 1129defaultTo : a -> Json.Decode.Decoder a -> Json.Decode.Decoder a 1130defaultTo default = 1131 Json.Decode.map (Maybe.withDefault default) << Json.Decode.maybe 1132 1133 1134customDecoder : Json.Decode.Decoder b -> (b -> Result Json.Decode.Error a) -> Json.Decode.Decoder a 1135customDecoder decoder toResult = 1136 Json.Decode.andThen 1137 (\a -> 1138 case toResult a of 1139 Ok b -> 1140 Json.Decode.succeed b 1141 1142 Err err -> 1143 Json.Decode.fail <| Json.Decode.errorToString err 1144 ) 1145 decoder 1146 1147 1148optionalField : String -> (a -> Json.Encode.Value) -> Maybe a -> Maybe ( String, Json.Encode.Value ) 1149optionalField field encoder = 1150 Maybe.map (\val -> ( field, encoder val )) 1151