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