xcodeapixcode-botsxcode-server

XCode Bots API configuration edit fails


I want to change via the XCode Bots API the scheme name of a bot. A request like curl -XPATCH -H 'Content-Type: application/json' -H 'x-xcsclientversion: 8' https://localhost:20343/api/bots/botid123 -d '{"name": "myawesomebot2"}' to change the bot name works. But if I try to change the configuration object with a request body like '{"configuration": {"schemeName": "scheme2"}}' it fails.

How can the scheme name be modified?


Solution

  • I finally got this solved and want to note the pieces necessary to make this work and how I found it.

    First, as you already noticed, is the need for -H "x-xcsclientversion: #" (note, 6 worked for me, as discovered through a check of Apple's Javascript that receives the PATCH request)

    Second, after watching Xcode Server update a bot through Charles, it was seen that the URL needs the following parameter added, ?overwriteBlueprint=true

    Third, it seems that the JSON data, at the topmost level as name:, also requires requiresUpgrade=false and type=1 (I found the tool jq to be invaluable)

    Fourth, changes to the sourceBlueprint requires configuration.sourceControlBlueprint.DVTSourceControlWorkspaceBlueprintIdentifierKey to receive a new UUID. Easily generated in bash by uuidgen command.

    Fifth, a mostly-full bot description must be sent. I grabbed the bot's JSON definition through Apple's API, then modified it using jq (see above), deleting out unnecessary key/value pairs so as to match Xcode Server's own API calls. The necessary key/value pairs appear to be:

    Sixth, backslash-escape all forward-slashes in the JSON payload. I've done this in bash with ESCAPED_JSON=${BOT_CONFIG_JSON//\//\\\/} and I send -d "$ESCAPED_JSON" in the curl command.

    As such, the full curl command I'm using becomes:

    curl -k --request PATCH -H "Content-Type: application/json" -H "x-xcsclientversion: 6" -d "$ESCAPED_JSON" https://<username>:<password>@<your_server_address>:20343/api/bots/<your_bot_id>?overwriteBlueprint=true
    

    And a full JSON definition (remember, it must have forward slashes escaped before sending) looks like this

    <!-- language: lang-json -->
      "requiresUpgrade": false,
      "configuration": {
        "triggers": [
          {
            "phase": 1,
            "scriptBody": "<REDACTED>",
            "type": 1,
            "name": "Update github Pending",
            "conditions": {
              "status": 2,
              "onSuccess": true,
              "onAnalyzerWarnings": true,
              "onBuildErrors": true,
              "onWarnings": true,
              "onFailingTests": true
            }
          },
          {
            "phase": 2,
            "scriptBody": "<REDACTED>",
            "type": 1,
            "name": "Upload to Beta",
            "conditions": {
              "status": 2,
              "onSuccess": true,
              "onAnalyzerWarnings": true,
              "onBuildErrors": false,
              "onWarnings": true,
              "onFailingTests": false
            }
          },
          {
            "phase": 2,
            "scriptBody": "<REDACTED>",
            "type": 1,
            "name": "Update github status",
            "conditions": {
              "status": 2,
              "onSuccess": true,
              "onAnalyzerWarnings": true,
              "onBuildErrors": false,
              "onWarnings": true,
              "onFailingTests": false
            }
          }
        ],
        "performsUpgradeIntegration": true,
        "disableAppThinning": true,
        "deviceSpecification": {
          "filters": [
            {
              "platform": {
                "_id": "3c884e2499df662057e8c64580003419",
                "displayName": "iOS",
                "_rev": "8-51c114fcfc83ea5f36df66f119b34ec8",
                "simulatorIdentifier": "com.apple.platform.iphonesimulator",
                "identifier": "com.apple.platform.iphoneos",
                "buildNumber": "14C89",
                "version": "10.2"
              },
              "filterType": 3,
              "architectureType": 0
            }
          ],
          "deviceIdentifiers": [
            "6d928bd891b83b4b8592aedb42001a97",
            "6d928bd891b83b4b8592aedb4200776c",
            "fa737f03db7b6c04d4c7f9507100700f"
          ]
        },
        "periodicScheduleInterval": 0,
        "schemeName": "<REDACTED>",
        "codeCoveragePreference": 2,
        "performsTestAction": true,
        "scheduleType": 3,
        "performsArchiveAction": true,
        "builtFromClean": 2,
        "buildConfiguration": "Release",
        "performsAnalyzeAction": true,
        "sourceControlBlueprint": {
          "DVTSourceControlWorkspaceBlueprintLocationsKey": {
            "A2739AD29C3BCDF8619D0305ACFDD0C22AEBDDB1": {
              "DVTSourceControlWorkspaceBlueprintLocationTypeKey": "DVTSourceControlLockedRevisionLocation",
              "DVTSourceControlLocationRevisionKey": "9d38dc7507f0f6ac17072d721893f0021c5282ed"
            },
            "51DBFAD1848AC646B864BBBEDC625B8BAB305A76": {
              "DVTSourceControlBranchIdentifierKey": "<THE BRANCH TO WATCH>",
              "DVTSourceControlBranchOptionsKey": 4,
              "DVTSourceControlWorkspaceBlueprintLocationTypeKey": "DVTSourceControlBranch"
            }
          },
          "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey": "51DBFAD1848AC646B864BBBEDC625B8BAB305A76",
          "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey": {},
          "DVTSourceControlWorkspaceBlueprintRemoteRepositoryAuthenticationStrategiesKey": {
            "A2739AD29C3BCDF8619D0305ACFDD0C22AEBDDB1": {
              "DVTSourceControlWorkspaceBlueprintRemoteRepositoryAuthenticationTypeKey": "DVTSourceControlAuthenticationStrategy"
            },
            "51DBFAD1848AC646B864BBBEDC625B8BAB305A76": {
              "DVTSourceControlWorkspaceBlueprintRemoteRepositoryAuthenticationTypeKey": "DVTSourceControlAuthenticationStrategy"
            }
          },
          "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey": {
            "A2739AD29C3BCDF8619D0305ACFDD0C22AEBDDB1": 0,
            "51DBFAD1848AC646B864BBBEDC625B8BAB305A76": 0
          },
          "DVTSourceControlWorkspaceBlueprintIdentifierKey": "<GENERATE A NEW UUID FOR THIS!!!>",
          "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey": {
            "A2739AD29C3BCDF8619D0305ACFDD0C22AEBDDB1": "<REDACTED PATH 1>",
            "51DBFAD1848AC646B864BBBEDC625B8BAB305A76": "<REDACTED PATH 2>"
          },
          "DVTSourceControlWorkspaceBlueprintNameKey": "Cool Blueprint",
          "DVTSourceControlWorkspaceBlueprintVersion": 204,
          "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey": "<REDACTED>.xcworkspace",
          "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey": [
            {
              "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey": "git@github.com:<REDACTED REPO 1>",
              "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey": "com.apple.dt.Xcode.sourcecontrol.Git",
              "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey": "A2739AD29C3BCDF8619D0305ACFDD0C22AEBDDB1"
            },
            {
              "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey": "git@github.com:<REDACTED REPO 2>",
              "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey": "com.apple.dt.Xcode.sourcecontrol.Git",
              "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey": "51DBFAD1848AC646B864BBBEDC625B8BAB305A76"
            }
          ]
        },
        "exportsProductFromArchive": true,
        "weeklyScheduleDay": 0,
        "minutesAfterHourToIntegrate": 0,
        "testingDestinationType": 0,
        "hourOfIntegration": 0,
        "testingDeviceIDs": []
      },
      "group": {
        "name": "41A62776-A72E-44C0-BFF0-D91F699BBA6A"
      },
      "type": 1,
      "name": "My Cool Integration Bot"
    

    I hope this helps.