2

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?

ideveloper
  • 473
  • 1
  • 4
  • 10
  • Did you ever figure this out? So far, in my testing, I've been able to set a -d JSON payload of '{"name": "cool_bot", "configuration": {"scheduleType": 2}}' and that's it. Modifications to something like sourceControlBlueprint (so I can point the bot to a new branch on the repo) either seem to be ignored or return a "Class of object ((null)) is not a subclass of XCSBotConfiguration" Similar problems for you, I guess? Did you ever arrive at a solution? – christopherdrum Feb 24 '17 at 07:34

1 Answers1

4

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:

  • name
  • type
  • requiresUpgrade
  • configuration (modify as necessary, but a full configuration must be sent)
  • group (leave as-is, but send it back through)

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.

christopherdrum
  • 1,513
  • 9
  • 25
  • in similar way xcode does update the bots. it sends a mostly complete config json object. to send only the updated property does not seem to work. even if the documentation says that it should work. – ideveloper Mar 03 '17 at 12:58
  • Exactly correct. Ultimately, my success came from mimicking what Xcode does as precisely as possible, including sending data that doesn't seem to be necessary (why resend every integration script again?!) – christopherdrum Mar 05 '17 at 23:43
  • Quick comment for those discovering and up-voting this, even 5 years later. I'd like to note that I have been using the above method unaltered this entire time with no problems. Solution still appears to be compatible (i.e. I have it in daily production use driving two critical build servers) with Xcode 13.4.1. – christopherdrum Jul 01 '22 at 05:50