Search code examples
bashjqfirebase-test-lab

Get the output of a jq command and iterate over them in a bash script


I have the following json that I need to parse values in a bash script.

{
  "matrix-2h44ka21lln62": {
    "projectId": "app-54934",
    "matrixId": "matrix-2h44ka21lln62",
    "state": "FINISHED",
    "gcsPath": "App-ios-runner/2023-02-07_13-55-43.444360_CdCC/shard_0",
    "webLink": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4663013071689981858/details",
    "downloaded": true,
    "billableMinutes": {
      "virtual": 0,
      "physical": 1
    },
    "clientDetails": {
      "Flank Version": "v23.01.0",
      "Flank Revision": "7ad3d5ba4097f189965110ca52b93fd0645715e0"
    },
    "gcsPathWithoutRootBucket": "2023-02-07_13-55-43.444360_CdCC/shard_0",
    "gcsRootBucket": "App-ios-runner",
    "axes": [
      {
        "device": "iphone8-15.7-en-portrait",
        "outcome": "failure",
        "details": "0 test cases failed",
        "suiteOverview": {
          "total": 0,
          "errors": 0,
          "failures": 0,
          "flakes": 0,
          "skipped": 0,
          "elapsedTime": 0,
          "overheadTime": 0
        }
      }
    ],
    "appFileName": "App-UISmokeTests.zip",
    "testFileName": "App-UISmokeTests_iphoneos16.2-arm64_shard_0.xctestrun",
    "isCompleted": false,
    "testExecutions": [
      {
        "id": "matrix-2h44ka21lln62_execution-clgfpxn2zgrta",
        "modelId": "iphone8",
        "deviceVersion": "15.7",
        "state": "FINISHED",
        "errorMessage": "",
        "progress": [
          "Starting attempt 1.",
          "Checking Internet connection...",
          "Internet connection stable!",
          "Starting iOS test.",
          "Completed iOS test.",
          "Done. Test time = 14 (secs)",
          "Starting results processing. Attempt: 1",
          "Completed results processing. Time taken = 3 (secs)"
        ],
        "toolResultsStep": {
          "executionId": "4663013071689981858",
          "historyId": "bh.388190097b1eab25",
          "projectId": "app-54934",
          "stepId": "bs.2b9b72bccab868fa"
        }
      }
    ],
    "testTimeout": 2700,
    "isRoboTest": false,
    "historyId": "",
    "executionId": "",
    "invalidMatrixDetails": "UNKNOWN",
    "outcome": "failure"
  },
  "matrix-8hj1qx8udleaa": {
    "projectId": "app-54934",
    "matrixId": "matrix-8hj1qx8udleaa",
    "state": "FINISHED",
    "gcsPath": "App-ios-runner/2023-02-07_13-55-43.444360_CdCC/shard_1",
    "webLink": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/5654175129805154564/details",
    "downloaded": true,
    "billableMinutes": {
      "virtual": 0,
      "physical": 1
    },
    "clientDetails": {
      "Flank Version": "v23.01.0",
      "Flank Revision": "7ad3d5ba4097f189965110ca52b93fd0645715e0"
    },
    "gcsPathWithoutRootBucket": "2023-02-07_13-55-43.444360_CdCC/shard_1",
    "gcsRootBucket": "App-ios-runner",
    "axes": [
      {
        "device": "iphone8-15.7-en-portrait",
        "outcome": "failure",
        "details": "0 test cases failed",
        "suiteOverview": {
          "total": 0,
          "errors": 0,
          "failures": 0,
          "flakes": 0,
          "skipped": 0,
          "elapsedTime": 0,
          "overheadTime": 0
        }
      }
    ],
    "appFileName": "App-UISmokeTests.zip",
    "testFileName": "App-UISmokeTests_iphoneos16.2-arm64_shard_1.xctestrun",
    "isCompleted": false,
    "testExecutions": [
      {
        "id": "matrix-8hj1qx8udleaa_execution-10jy4hq8i62g4",
        "modelId": "iphone8",
        "deviceVersion": "15.7",
        "state": "FINISHED",
        "errorMessage": "",
        "progress": [
          "Starting attempt 1.",
          "Checking Internet connection...",
          "Internet connection stable!",
          "Starting iOS test.",
          "Completed iOS test.",
          "Done. Test time = 15 (secs)",
          "Starting results processing. Attempt: 1",
          "Completed results processing. Time taken = 4 (secs)"
        ],
        "toolResultsStep": {
          "executionId": "5654175129805154564",
          "historyId": "bh.388190097b1eab25",
          "projectId": "app-54934",
          "stepId": "bs.b7d2f90beed6230a"
        }
      }
    ],
    "testTimeout": 2700,
    "isRoboTest": false,
    "historyId": "",
    "executionId": "",
    "invalidMatrixDetails": "UNKNOWN",
    "outcome": "failure"
  },
  "matrix-2i6y9uq9i0ext": {
    "projectId": "app-54934",
    "matrixId": "matrix-2i6y9uq9i0ext",
    "state": "FINISHED",
    "gcsPath": "App-ios-runner/2023-02-07_13-55-43.444360_CdCC/shard_2",
    "webLink": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4958041021718608851/details",
    "downloaded": true,
    "billableMinutes": {
      "virtual": 0,
      "physical": 1
    },
    "clientDetails": {
      "Flank Version": "v23.01.0",
      "Flank Revision": "7ad3d5ba4097f189965110ca52b93fd0645715e0"
    },
    "gcsPathWithoutRootBucket": "2023-02-07_13-55-43.444360_CdCC/shard_2",
    "gcsRootBucket": "App-ios-runner",
    "axes": [
      {
        "device": "iphone8-15.7-en-portrait",
        "outcome": "failure",
        "details": "0 test cases failed",
        "suiteOverview": {
          "total": 0,
          "errors": 0,
          "failures": 0,
          "flakes": 0,
          "skipped": 0,
          "elapsedTime": 0,
          "overheadTime": 0
        }
      }
    ],
    "appFileName": "App-UISmokeTests.zip",
    "testFileName": "App-UISmokeTests_iphoneos16.2-arm64_shard_2.xctestrun",
    "isCompleted": false,
    "testExecutions": [
      {
        "id": "matrix-2i6y9uq9i0ext_execution-1zvntyq5awzyv",
        "modelId": "iphone8",
        "deviceVersion": "15.7",
        "state": "FINISHED",
        "errorMessage": "",
        "progress": [
          "Starting attempt 1.",
          "Checking Internet connection...",
          "Internet connection stable!",
          "Starting iOS test.",
          "Completed iOS test.",
          "Done. Test time = 13 (secs)",
          "Starting results processing. Attempt: 1",
          "Completed results processing. Time taken = 5 (secs)"
        ],
        "toolResultsStep": {
          "executionId": "4958041021718608851",
          "historyId": "bh.388190097b1eab25",
          "projectId": "app-54934",
          "stepId": "bs.283070cfe31b0c"
        }
      }
    ],
    "testTimeout": 2700,
    "isRoboTest": false,
    "historyId": "",
    "executionId": "",
    "invalidMatrixDetails": "UNKNOWN",
    "outcome": "failure"
  }
}

I went with jq to parse these results but I'm stuck on how to iterate values over the output of my jq command

jq -c --raw-output '.[] | {matrixId: .matrixId, state: .state, details: .axes[].details, device: .axes[].device, webLink: .webLink} | to_entries | map({key:.key, value:.value})'

I want to get the following result

[
  {
    "key": "matrixId",
    "value": "matrix-2h44ka21lln62"
  },
  {
    "key": "state",
    "value": "FINISHED"
  },
  {
    "key": "details",
    "value": "0 test cases failed"
  },
  {
    "key": "device",
    "value": "iphone8-15.7-en-portrait"
  },
  {
    "key": "webLink",
    "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4663013071689981858/details"
  }
],
[
  {
    "key": "matrixId",
    "value": "matrix-8hj1qx8udleaa"
  },
  {
    "key": "state",
    "value": "FINISHED"
  },
  {
    "key": "details",
    "value": "0 test cases failed"
  },
  {
    "key": "device",
    "value": "iphone8-15.7-en-portrait"
  },
  {
    "key": "webLink",
    "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/5654175129805154564/details"
  }
],
[
  {
    "key": "matrixId",
    "value": "matrix-2i6y9uq9i0ext"
  },
  {
    "key": "state",
    "value": "FINISHED"
  },
  {
    "key": "details",
    "value": "0 test cases failed"
  },
  {
    "key": "device",
    "value": "iphone8-15.7-en-portrait"
  },
  {
    "key": "webLink",
    "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4958041021718608851/details"
  }
]

It returns the output as three array objects with no comma separated value which is blocking me on iterating over them

I tried to search on how can I join them through piping but it's not working as expected


Solution

  • .[] iterates over the elements in an array and returns a stream of elements. So the input [1,2,3] will be returned as 1 2 3 when filtered through .[].

    Now you could stream the array's elements, apply a transformation, and then collect them again: [.[] | f], but hold on. There's a better way: map(f).

    Applying this idea to your program gives:

    jq -c 'map({matrixId, state, details: .axes[].details, device: .axes[].device, webLink} | to_entries[])'
    

    (Not sure why you have to_entries | map({key:.key, value:.value}), because to_entries already returns objects of that form.)

    Output:

    [
      {
        "key": "matrixId",
        "value": "matrix-2h44ka21lln62"
      },
      {
        "key": "state",
        "value": "FINISHED"
      },
      {
        "key": "details",
        "value": "0 test cases failed"
      },
      {
        "key": "device",
        "value": "iphone8-15.7-en-portrait"
      },
      {
        "key": "webLink",
        "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4663013071689981858/details"
      },
      {
        "key": "matrixId",
        "value": "matrix-8hj1qx8udleaa"
      },
      {
        "key": "state",
        "value": "FINISHED"
      },
      {
        "key": "details",
        "value": "0 test cases failed"
      },
      {
        "key": "device",
        "value": "iphone8-15.7-en-portrait"
      },
      {
        "key": "webLink",
        "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/5654175129805154564/details"
      },
      {
        "key": "matrixId",
        "value": "matrix-2i6y9uq9i0ext"
      },
      {
        "key": "state",
        "value": "FINISHED"
      },
      {
        "key": "details",
        "value": "0 test cases failed"
      },
      {
        "key": "device",
        "value": "iphone8-15.7-en-portrait"
      },
      {
        "key": "webLink",
        "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4958041021718608851/details"
      }
    ]
    

    If you want an array of arrays, then don't iterate to_entries and simply map to the entries array:

    jq 'map({matrixId, state, details: .axes[].details, device: .axes[].device, webLink} | to_entries)'
    

    Output:

    [
      [
        {
          "key": "matrixId",
          "value": "matrix-2h44ka21lln62"
        },
        {
          "key": "state",
          "value": "FINISHED"
        },
        {
          "key": "details",
          "value": "0 test cases failed"
        },
        {
          "key": "device",
          "value": "iphone8-15.7-en-portrait"
        },
        {
          "key": "webLink",
          "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4663013071689981858/details"
        }
      ],
      [
        {
          "key": "matrixId",
          "value": "matrix-8hj1qx8udleaa"
        },
        {
          "key": "state",
          "value": "FINISHED"
        },
        {
          "key": "details",
          "value": "0 test cases failed"
        },
        {
          "key": "device",
          "value": "iphone8-15.7-en-portrait"
        },
        {
          "key": "webLink",
          "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/5654175129805154564/details"
        }
      ],
      [
        {
          "key": "matrixId",
          "value": "matrix-2i6y9uq9i0ext"
        },
        {
          "key": "state",
          "value": "FINISHED"
        },
        {
          "key": "details",
          "value": "0 test cases failed"
        },
        {
          "key": "device",
          "value": "iphone8-15.7-en-portrait"
        },
        {
          "key": "webLink",
          "value": "https://console.firebase.google.com/project/app-54934/testlab/histories/bh.388190097b1eab25/matrices/4958041021718608851/details"
        }
      ]
    ]