From 49a3b5fa0510166f59bace602a0d386279159141 Mon Sep 17 00:00:00 2001 From: haibo Date: Sun, 5 Apr 2026 11:48:50 -0700 Subject: [PATCH 01/21] fix: detect container architecture for Fabric binary download in agent Dockerfile The agent Dockerfile hardcoded linux-amd64 for the Fabric binary download, causing cryptogen to crash with SIGTRAP on ARM64 hosts (e.g., Apple Silicon). - Use dpkg --print-architecture for reliable arch detection - Fail build on unsupported architectures instead of silently defaulting to amd64 - Add curl --fail flag to catch HTTP errors early Signed-off-by: haibo Signed-off-by: khanak0509 --- src/agents/hyperledger-fabric/Dockerfile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/agents/hyperledger-fabric/Dockerfile b/src/agents/hyperledger-fabric/Dockerfile index 14e1b9300..978023519 100644 --- a/src/agents/hyperledger-fabric/Dockerfile +++ b/src/agents/hyperledger-fabric/Dockerfile @@ -13,7 +13,12 @@ COPY . . RUN mkdir cello # Install compiled code tools from Artifactory and copy it to opt folder. -RUN curl -L --retry 5 --retry-delay 3 "https://github.com/hyperledger/fabric/releases/download/v2.5.14/hyperledger-fabric-linux-amd64-2.5.14.tar.gz" | tar xz -C ./cello/ +RUN ARCH=$(dpkg --print-architecture) && \ + case "$ARCH" in \ + amd64|arm64) FABRIC_ARCH="$ARCH" ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac && \ + curl -fsSL --retry 5 --retry-delay 3 "https://github.com/hyperledger/fabric/releases/download/v2.5.14/hyperledger-fabric-linux-${FABRIC_ARCH}-2.5.14.tar.gz" | tar xz -C ./cello/ # Install python dependencies RUN pip3 install -r requirements.txt From e3d307d7132afdeb720abd04b88aacbef3bff588 Mon Sep 17 00:00:00 2001 From: khanak0509 Date: Sat, 9 May 2026 20:26:10 +0530 Subject: [PATCH 02/21] fix: auto-fill chaincode sequence with default value of 1 Signed-off-by: khanak0509 --- .../chaincode/serializers.py | 2 +- src/api-engine/chaincode/models.py | 1 + src/api-engine/chaincode/serializers.py | 4 +++- .../src/pages/ChainCode/forms/UploadForm.js | 19 +------------------ 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/agents/hyperledger-fabric/chaincode/serializers.py b/src/agents/hyperledger-fabric/chaincode/serializers.py index f6d449a7d..2876d2806 100644 --- a/src/agents/hyperledger-fabric/chaincode/serializers.py +++ b/src/agents/hyperledger-fabric/chaincode/serializers.py @@ -58,7 +58,7 @@ class ChaincodeResponseSerializer(serializers.Serializer): class ChaincodeCreationSerializer(serializers.Serializer): name = serializers.CharField(help_text="Chaincode Name") version = serializers.CharField(help_text="Chaincode Version") - sequence = serializers.IntegerField(help_text="Chaincode Sequence") + sequence = serializers.IntegerField(help_text="Chaincode Sequence", required=False, default=1) channel_name = serializers.CharField(help_text="Chaincode Channel Name") file = serializers.FileField(help_text="Chaincode File") init_required = serializers.BooleanField(help_text="Chaincode Required Initialization") diff --git a/src/api-engine/chaincode/models.py b/src/api-engine/chaincode/models.py index 5fd15d6e2..eef82cde8 100644 --- a/src/api-engine/chaincode/models.py +++ b/src/api-engine/chaincode/models.py @@ -48,6 +48,7 @@ class Status(models.TextChoices): sequence = models.IntegerField( help_text="Chaincode Sequence", validators=[MinValueValidator(1)], + default=1, ) label = models.CharField( help_text="Chaincode Label", diff --git a/src/api-engine/chaincode/serializers.py b/src/api-engine/chaincode/serializers.py index 8e1667b30..33fdb74db 100644 --- a/src/api-engine/chaincode/serializers.py +++ b/src/api-engine/chaincode/serializers.py @@ -88,7 +88,9 @@ class Meta: ) extra_kwargs = { "sequence": { - "validators": [MinValueValidator(1)] + "validators": [MinValueValidator(1)], + "required": False, + "default": 1 }, "init_required": {"required": False}, "signature_policy": {"required": False}, diff --git a/src/dashboard/src/pages/ChainCode/forms/UploadForm.js b/src/dashboard/src/pages/ChainCode/forms/UploadForm.js index 9f12fb5d4..0f58680f4 100644 --- a/src/dashboard/src/pages/ChainCode/forms/UploadForm.js +++ b/src/dashboard/src/pages/ChainCode/forms/UploadForm.js @@ -178,24 +178,7 @@ const UploadForm = props => { > - - - + Date: Sun, 10 May 2026 23:14:41 +0530 Subject: [PATCH 03/21] remove unused InputNumber import Signed-off-by: khanak0509 --- src/dashboard/src/pages/ChainCode/forms/UploadForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dashboard/src/pages/ChainCode/forms/UploadForm.js b/src/dashboard/src/pages/ChainCode/forms/UploadForm.js index 0f58680f4..035961ba8 100644 --- a/src/dashboard/src/pages/ChainCode/forms/UploadForm.js +++ b/src/dashboard/src/pages/ChainCode/forms/UploadForm.js @@ -1,6 +1,6 @@ import { useState, useEffect } from 'react'; import { injectIntl, useIntl } from 'umi'; -import { Button, Modal, Input, Upload, message, Switch, Select, InputNumber, Tag } from 'antd'; +import { Button, Modal, Input, Upload, message, Switch, Select, Tag } from 'antd'; import { UploadOutlined } from '@ant-design/icons'; import { Form } from 'antd/lib/index'; import { listChannel } from '@/services/channel'; From 6cedd290a1c9daca080472c873eeab3fd0d87847 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 11 Apr 2026 07:28:35 +0800 Subject: [PATCH 04/21] Remove redundant postman info Some info of the postman collection is unnecessary for the newman test, so they shouldn't be pushed on Git. Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .github/workflows/check-code.yml | 5 +++++ .../collections/Cello Engine CI Test.postman_collection.json | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-code.yml b/.github/workflows/check-code.yml index 98e1bf414..776bd7474 100644 --- a/.github/workflows/check-code.yml +++ b/.github/workflows/check-code.yml @@ -12,21 +12,26 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Set up Python uses: actions/setup-python@v4 with: python-version: "3.8" + - name: Set up Nodejs uses: actions/setup-node@v3 with: node-version: "20" + - name: Install Python dependencies run: | python -m pip install --upgrade pip python -m pip install tox tox-gh-actions + - name: Install Nodejs dependencies working-directory: src/dashboard run: | yarn install --frozen-lockfile + - name: Check code run: make check diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index fa5c4e7b0..cca63dad9 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -1,10 +1,7 @@ { "info": { - "_postman_id": "04314160-39b9-401c-b74f-6ea9f1cd89fd", "name": "Cello Engine CI Test", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "43793131", - "_collection_link": "https://www.postman.com/haiboyang-3238546/workspace/hyperledger-cello/collection/43793131-04314160-39b9-401c-b74f-6ea9f1cd89fd?action=share&source=collection_link&creator=43793131" + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { From d4416308ba1a58bc471000d03d52c2f030e5ac3e Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 11 Apr 2026 08:02:06 +0800 Subject: [PATCH 05/21] Test create orgs via registration Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 615 +----------------- ...ker-compose.dev.yml => docker-compose.yml} | 1 - 2 files changed, 4 insertions(+), 612 deletions(-) rename tests/postman/{docker-compose.dev.yml => docker-compose.yml} (94%) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index cca63dad9..9e52d41da 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -11,11 +11,11 @@ "listen": "test", "script": { "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", "});", "", - "if (pm.response.code === 200) {", + "if (pm.response.code === 201) {", " var jsonData = pm.response.json();", " pm.environment.set(\"org_id\", jsonData.data.id);", "}" @@ -35,7 +35,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"email\": \"foo@email.com\",\n\t\"password\": \"foo\",\n\t\"orgName\": \"org1.foo.com\"\n}" + "raw": "{\n\t\"email\": \"foo@email.com\",\n\t\"password\": \"foo\",\n\t\"org_name\": \"org1.foo.com\",\n\t\"agent_url\": \"http://cello-hyperledger-fabric-agent:8080/api/v1/\"\n}" }, "url": { "raw": "{{base_url}}/api/v1/register", @@ -50,578 +50,6 @@ }, "description": "Register new user with organization" } - }, - { - "name": "Login User", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "if (pm.response.code === 200) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"token\", jsonData.data.token);", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"email\": \"foo@email.com\",\n\t\"password\": \"foo\"\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/login", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "login" - ] - }, - "description": "Login with email and password to get access token" - } - }, - { - "name": "Create Agent", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"agent_id\", jsonData.data.id);", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"name\": \"cello-agent-docker\",\n\t\"type\": \"docker\",\n\t\"urls\": \"http://cello.docker.agent:5001\"\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/agents", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "agents" - ] - }, - "description": "Create new agent" - } - }, - { - "name": "Create Peer Node", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"peer_id\", jsonData.data.id);", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"name\": \"peer0\",\n\t\"type\": \"peer\"\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/nodes", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "nodes" - ] - }, - "description": "Create new peer node" - } - }, - { - "name": "Create Orderer Node", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"orderer_id\", jsonData.data.id);", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"name\": \"orderer0\",\n\t\"type\": \"orderer\"\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/nodes", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "nodes" - ] - }, - "description": "Create new orderer node" - } - }, - { - "name": "Create Network", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"network_id\", jsonData.data.id);", - " ", - " setTimeout(function() {", - " console.log(\"Delayed 5 seconds\");", - " }, 5000);", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"name\": \"test-network\",\n\t\"consensus\": \"etcdraft\",\n\t\"database\": \"couchdb\"\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/networks", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "networks" - ] - }, - "description": "Create new blockchain network" - } - }, - { - "name": "Create Channel", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"channel_id\", jsonData.id);", - " ", - " setTimeout(function() {", - " console.log(\"Delayed 10 seconds\");", - " }, 10000);", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"name\": \"mychannel\",\n\t\"orderers\": [\"{{orderer_id}}\"],\n\t\"peers\": [\"{{peer_id}}\"]\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/channels", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "channels" - ] - }, - "description": "Create new channel with specified peers and orderers" - } - }, - { - "name": "Upload Chaincode Package", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "formdata", - "formdata": [ - { - "key": "file", - "type": "file", - "src": ["basic.tar.gz"], - "description": "basic chaincode package" - }, - { - "key": "description", - "value": "Sample chaincode for testing", - "type": "text" - } - ] - }, - "url": { - "raw": "{{base_url}}/api/v1/chaincodes/chaincodeRepo", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "chaincodes", - "chaincodeRepo" - ] - }, - "description": "Upload chaincode package file" - } - }, - { - "name": "List Chaincodes", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "if (pm.response.code === 200) {", - " var jsonData = pm.response.json();", - " if (jsonData.data && jsonData.data.data && jsonData.data.data.length > 0) {", - " var latestChaincode = jsonData.data.data[0];", - " pm.environment.set(\"package_id\", latestChaincode.package_id);", - " } else {", - " console.log(\"No chaincodes found in response\");", - " }", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [ - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "url": { - "raw": "{{base_url}}/api/v1/chaincodes?page=1&per_page=10", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "chaincodes" - ], - "query": [ - { - "key": "page", - "value": "1" - }, - { - "key": "per_page", - "value": "10" - } - ] - }, - "description": "List chaincodes to get the latest uploaded chaincode ID" - } - }, - { - "name": "Install Chaincode", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"id\": \"{{package_id}}\",\n\t\"node\": \"{{peer_id}}\"\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/chaincodes/install", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "chaincodes", - "install" - ] - }, - "description": "Install chaincode package to peer node" - } - }, - { - "name": "Approve Chaincode", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"channel_name\": \"mychannel\",\n\t\"chaincode_name\": \"basic\",\n\t\"chaincode_version\": \"1.0\",\n\t\"sequence\": 1,\n\t\"policy\": \"\",\n\t\"init_flag\": false\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/chaincodes/approve_for_my_org", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "chaincodes", - "approve_for_my_org" - ] - }, - "description": "Approve chaincode for organization" - } - }, - { - "name": "Commit Chaincode", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "Authorization", - "value": "JWT {{token}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"channel_name\": \"mychannel\",\n\t\"chaincode_name\": \"basic\",\n\t\"chaincode_version\": \"1.0\",\n\t\"sequence\": 1,\n\t\"policy\": \"\",\n\t\"init_flag\": false\n}" - }, - "url": { - "raw": "{{base_url}}/api/v1/chaincodes/commit", - "host": [ - "{{base_url}}" - ], - "path": [ - "api", - "v1", - "chaincodes", - "commit" - ] - }, - "description": "Commit chaincode definition to channel" - } } ], "variable": [ @@ -630,45 +58,10 @@ "value": "http://127.0.0.1:8080", "type": "string" }, - { - "key": "token", - "value": "", - "type": "string" - }, { "key": "org_id", "value": "", "type": "string" - }, - { - "key": "agent_id", - "value": "", - "type": "string" - }, - { - "key": "network_id", - "value": "", - "type": "string" - }, - { - "key": "peer_id", - "value": "", - "type": "string" - }, - { - "key": "orderer_id", - "value": "", - "type": "string" - }, - { - "key": "channel_id", - "value": "", - "type": "string" - }, - { - "key": "package_id", - "value": "", - "type": "string" } ] } \ No newline at end of file diff --git a/tests/postman/docker-compose.dev.yml b/tests/postman/docker-compose.yml similarity index 94% rename from tests/postman/docker-compose.dev.yml rename to tests/postman/docker-compose.yml index d23b72e16..33d42529a 100644 --- a/tests/postman/docker-compose.dev.yml +++ b/tests/postman/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3.2' services: newman: image: postman/newman:latest From fa05f81518dd76895628eb6d7d5bc662d5ed4223 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 11 Apr 2026 08:10:36 +0800 Subject: [PATCH 06/21] Add newman tests to the CI pipeline Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .github/workflows/docker-image.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 2ed4ebe6a..efcebeca6 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -26,6 +26,10 @@ jobs: working-directory: src/nodes/hyperledger-fabric run: docker build -t hyperledger/fabric:2.5.14 . + - name: Run newman tests + working-directory: tests/postman + run: docker compose up --abort-on-container-exit + - name: Stop Hyperledger Fabric Agent run: docker stop cello-hyperledger-fabric-agent From 56bdae5b00042e966631ac0722a81589b22efe98 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 11 Apr 2026 08:13:18 +0800 Subject: [PATCH 07/21] Rename pipelines The pipeline names can be more specific about their actual purposes. Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .github/workflows/check-code.yml | 2 +- .github/workflows/docker-image.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-code.yml b/.github/workflows/check-code.yml index 776bd7474..ee739efd2 100644 --- a/.github/workflows/check-code.yml +++ b/.github/workflows/check-code.yml @@ -1,4 +1,4 @@ -name: Code Check CI +name: Lint Check on: push: diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index efcebeca6..3158a81ae 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,4 +1,4 @@ -name: Cello CI +name: Integration Tests on: push: From 30ba9d4a7bc7d1f088ceda49be979478fd9a0b36 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 11 Apr 2026 08:15:57 +0800 Subject: [PATCH 08/21] Rename workflow files Rename workflow files according to their new action name. Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .github/workflows/{docker-image.yml => integration-tests.yml} | 0 .github/workflows/{check-code.yml => lint-check.yml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{docker-image.yml => integration-tests.yml} (100%) rename .github/workflows/{check-code.yml => lint-check.yml} (100%) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/integration-tests.yml similarity index 100% rename from .github/workflows/docker-image.yml rename to .github/workflows/integration-tests.yml diff --git a/.github/workflows/check-code.yml b/.github/workflows/lint-check.yml similarity index 100% rename from .github/workflows/check-code.yml rename to .github/workflows/lint-check.yml From a88b3c792edd6bb6913a8b84722653d81721af79 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 11 Apr 2026 08:30:32 +0800 Subject: [PATCH 09/21] Add the login test back Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index 9e52d41da..1ceb973fa 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -50,6 +50,53 @@ }, "description": "Register new user with organization" } + }, + { + "name": "Login User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "if (pm.response.code === 200) {", + " var jsonData = pm.response.json();", + " pm.environment.set(\"token\", jsonData.data.token);", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"email\": \"foo@email.com\",\n\t\"password\": \"foo\"\n}" + }, + "url": { + "raw": "{{base_url}}/api/v1/login", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "v1", + "login" + ] + }, + "description": "Login with email and password to get access token" + } } ], "variable": [ @@ -58,6 +105,11 @@ "value": "http://127.0.0.1:8080", "type": "string" }, + { + "key": "token", + "value": "", + "type": "string" + }, { "key": "org_id", "value": "", From 102da03f4e56e5ae3d1fa02314c4ae070384c5fe Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 11 Apr 2026 08:45:31 +0800 Subject: [PATCH 10/21] Add the peer creation test Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index 1ceb973fa..d751088ca 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -97,6 +97,58 @@ }, "description": "Login with email and password to get access token" } + }, + { + "name": "Create A Peer", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "if (pm.response.code === 201) {", + " var jsonData = pm.response.json();", + " pm.environment.set(\"peer_id\", jsonData.data.id);", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Authorization", + "value": "JWT {{token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"name\": \"peer0\",\n\t\"type\": \"PEER\"\n}" + }, + "url": { + "raw": "{{base_url}}/api/v1/nodes", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "v1", + "nodes" + ] + }, + "description": "Create a new peer" + } } ], "variable": [ @@ -114,6 +166,11 @@ "key": "org_id", "value": "", "type": "string" + }, + { + "key": "peer_id", + "value": "", + "type": "string" } ] } \ No newline at end of file From a87e9ec1d04f88738a7b7129d62fa3501115b82c Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Tue, 14 Apr 2026 09:12:10 +0800 Subject: [PATCH 11/21] Add an orderer creation test Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .github/workflows/integration-tests.yml | 3 + ...llo Engine CI Test.postman_collection.json | 57 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 3158a81ae..0457c2332 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -30,6 +30,9 @@ jobs: working-directory: tests/postman run: docker compose up --abort-on-container-exit + - name: Stop Hyperledger Fabric Nodes + run: docker stop orderer0.foo.com peer0.org1.foo.com + - name: Stop Hyperledger Fabric Agent run: docker stop cello-hyperledger-fabric-agent diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index d751088ca..54bc1b9ee 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -149,6 +149,58 @@ }, "description": "Create a new peer" } + }, + { + "name": "Create An Orderer", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "if (pm.response.code === 201) {", + " var jsonData = pm.response.json();", + " pm.environment.set(\"orderer_id\", jsonData.data.id);", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Authorization", + "value": "JWT {{token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"name\": \"orderer0\",\n\t\"type\": \"ORDERER\"\n}" + }, + "url": { + "raw": "{{base_url}}/api/v1/nodes", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "v1", + "nodes" + ] + }, + "description": "Create a new orderer" + } } ], "variable": [ @@ -171,6 +223,11 @@ "key": "peer_id", "value": "", "type": "string" + }, + { + "key": "orderer_id", + "value": "", + "type": "string" } ] } \ No newline at end of file From 5d9586fa02003184b720f5b22ca6bbf1cd7d5b74 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Tue, 14 Apr 2026 13:25:55 +0800 Subject: [PATCH 12/21] Add a channel creation test Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index 54bc1b9ee..0412828f7 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -201,6 +201,58 @@ }, "description": "Create a new orderer" } + }, + { + "name": "Create A Channel", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "if (pm.response.code === 201) {", + " var jsonData = pm.response.json();", + " pm.environment.set(\"channel_id\", jsonData.id);", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Authorization", + "value": "JWT {{token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"name\": \"channel0\"\n}" + }, + "url": { + "raw": "{{base_url}}/api/v1/channels", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "v1", + "channels" + ] + }, + "description": "Create a new channel" + } } ], "variable": [ @@ -228,6 +280,11 @@ "key": "orderer_id", "value": "", "type": "string" + }, + { + "key": "channel_id", + "value": "", + "type": "string" } ] } \ No newline at end of file From a6ae05fe1a04750d0e2b5988091ac38c54c47973 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 24 Apr 2026 12:38:10 +0800 Subject: [PATCH 13/21] Add a chaincode creation test Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index 0412828f7..46c8ca1db 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -215,7 +215,7 @@ "", "if (pm.response.code === 201) {", " var jsonData = pm.response.json();", - " pm.environment.set(\"channel_id\", jsonData.id);", + " pm.environment.set(\"channel_id\", jsonData.data.id);", "}" ], "type": "text/javascript" @@ -253,6 +253,74 @@ }, "description": "Create a new channel" } + }, + { + "name": "Upload a Chaincode", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "JWT {{token}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "name", + "value": "basic", + "type": "text" + }, + { + "key": "version", + "value": "1.0", + "type": "text" + }, + { + "key": "sequence", + "value": "1", + "type": "text" + }, + { + "key": "package", + "type": "file", + "src": ["basic.tar.gz"] + }, + { + "key": "channel", + "value": "{{channel_id}}", + "type": "text" + } + ] + }, + "url": { + "raw": "{{base_url}}/api/v1/chaincodes", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "v1", + "chaincodes" + ] + }, + "description": "Create a new chaincode" + } } ], "variable": [ From 61629c4478793393efce6e3ae304cbc21245f74a Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 24 Apr 2026 14:54:38 +0800 Subject: [PATCH 14/21] Bump Hyperledger Fabric to 2.5.15 In order to use the latest docker (29+), Hyperledger Fabric used in this project is bumped to 2.5.15 Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .github/workflows/integration-tests.yml | 2 +- src/agents/hyperledger-fabric/Dockerfile | 4 +++- src/agents/hyperledger-fabric/chaincode/serializers.py | 2 +- .../hyperledger-fabric/hyperledger_fabric/settings.py | 2 +- src/nodes/hyperledger-fabric/Dockerfile | 6 +++--- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 0457c2332..aa9aa1bd2 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Build Hyperledger Fabric Node working-directory: src/nodes/hyperledger-fabric - run: docker build -t hyperledger/fabric:2.5.14 . + run: docker build -t hyperledger/fabric:2.5.15 . - name: Run newman tests working-directory: tests/postman diff --git a/src/agents/hyperledger-fabric/Dockerfile b/src/agents/hyperledger-fabric/Dockerfile index 978023519..7908d6fbd 100644 --- a/src/agents/hyperledger-fabric/Dockerfile +++ b/src/agents/hyperledger-fabric/Dockerfile @@ -1,5 +1,7 @@ FROM python:3.13 +ENV FABRIC_VERSION=2.5.15 + # Install software RUN apt-get update\ && apt-get autoclean\ @@ -18,7 +20,7 @@ RUN ARCH=$(dpkg --print-architecture) && \ amd64|arm64) FABRIC_ARCH="$ARCH" ;; \ *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ esac && \ - curl -fsSL --retry 5 --retry-delay 3 "https://github.com/hyperledger/fabric/releases/download/v2.5.14/hyperledger-fabric-linux-${FABRIC_ARCH}-2.5.14.tar.gz" | tar xz -C ./cello/ + curl -fsSL --retry 5 --retry-delay 3 "https://github.com/hyperledger/fabric/releases/download/v${FABRIC_VERSION}/hyperledger-fabric-linux-${FABRIC_ARCH}-${FABRIC_VERSION}.tar.gz" | tar xz -C ./cello/ # Install python dependencies RUN pip3 install -r requirements.txt diff --git a/src/agents/hyperledger-fabric/chaincode/serializers.py b/src/agents/hyperledger-fabric/chaincode/serializers.py index 2876d2806..4bcd04e36 100644 --- a/src/agents/hyperledger-fabric/chaincode/serializers.py +++ b/src/agents/hyperledger-fabric/chaincode/serializers.py @@ -117,7 +117,7 @@ def create(self, validated_data): threading.Thread( target=install_chaincode, - args=(fs.path(filename)), + args=(fs.path(filename),), daemon=True).start() return self diff --git a/src/agents/hyperledger-fabric/hyperledger_fabric/settings.py b/src/agents/hyperledger-fabric/hyperledger_fabric/settings.py index 438decd04..60dd08c85 100644 --- a/src/agents/hyperledger-fabric/hyperledger_fabric/settings.py +++ b/src/agents/hyperledger-fabric/hyperledger_fabric/settings.py @@ -131,7 +131,7 @@ CELLO_HOME = os.path.join(BASE_DIR, "cello") CRYPTO_CONFIG = os.path.join(CELLO_HOME, "crypto-config.yaml") FABRIC_TOOL = os.path.join(CELLO_HOME, "bin") -FABRIC_VERSION = "2.5.14" +FABRIC_VERSION = "2.5.15" LOGGING = { "version": 1, diff --git a/src/nodes/hyperledger-fabric/Dockerfile b/src/nodes/hyperledger-fabric/Dockerfile index 5fe7bbae1..9460fbfc5 100644 --- a/src/nodes/hyperledger-fabric/Dockerfile +++ b/src/nodes/hyperledger-fabric/Dockerfile @@ -21,7 +21,7 @@ # Workdir is set to $GOPATH/src/github.com/hyperledger/fabric # Data is stored under /var/hyperledger/production -FROM golang:1.25.5 +FROM golang:1.26.2 LABEL maintainer="Baohua Yang " # Orderer, peer, ca, operation api @@ -34,10 +34,10 @@ ENV FABRIC_ROOT=$GOPATH/src/github.com/hyperledger/fabric \ FABRIC_CA_ROOT=$GOPATH/src/github.com/hyperledger/fabric-ca # BASE_VERSION is used in metadata.Version as major version -ENV BASE_VERSION=2.5.14 +ENV BASE_VERSION=2.5.15 # PROJECT_VERSION is required in core.yaml for fabric-baseos and fabric-ccenv -ENV PROJECT_VERSION=2.5.14 +ENV PROJECT_VERSION=2.5.15 ENV HLF_CA_VERSION=1.5.16 # generic environment (core.yaml) for builder and runtime: e.g., builder: $(DOCKER_NS)/fabric-ccenv:$(TWO_DIGIT_VERSION), golang, java, node From c56b6ae5ad7f88a575d3befbcae0bd2778d1e481 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 24 Apr 2026 17:03:39 +0800 Subject: [PATCH 15/21] Wait for the chaincode to be approved Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 105 +++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index 46c8ca1db..8c3aa330a 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -263,7 +263,12 @@ "exec": [ "pm.test(\"Status code is 201\", function () {", " pm.response.to.have.status(201);", - "});" + "});", + "", + "if (pm.response.code === 201) {", + " var jsonData = pm.response.json();", + " pm.environment.set(\"chaincode_id\", jsonData.data.id);", + "}" ], "type": "text/javascript" } @@ -321,6 +326,94 @@ }, "description": "Create a new chaincode" } + }, + { + "name": "Wait for the chaincode to be approved", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": { + "raw": "https://postman-echo.com/delay/60", + "host": [ + "postman-echo.com" + ], + "path": [ + "delay", + "60" + ], + "query": [] + }, + "description": "Wait a minute" + } + }, + { + "name": "Check if the chaincode is approved", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let json = pm.response.json();", + "let chaincode = json.data.data[0];", + "let status = chaincode.status;", + "", + "let retries = pm.environment.get(\"retries\");", + "if (status !== \"APPROVED\" && retries < 5) {", + " console.log(`Not ready (status=${status}), retry #${retries}`);", + " pm.environment.set(\"retries\", retries + 1);", + " pm.execution.setNextRequest(\"Wait for the chaincode to be approved\");", + "} else if (retries === 5) {", + " pm.expect.fail(`Max retries reached. Last status: ${status}`);", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "JWT {{token}}", + "type": "text" + } + ], + "url": { + "raw": "{{base_url}}/api/v1/chaincodes?page=1&per_page=10", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "v1", + "chaincodes" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "per_page", + "value": "10" + } + ] + }, + "description": "List chaincodes to check if it's been approved" + } } ], "variable": [ @@ -353,6 +446,16 @@ "key": "channel_id", "value": "", "type": "string" + }, + { + "key": "retries", + "value": 0, + "type": "number" + }, + { + "key": "chaincode_id", + "value": "", + "type": "string" } ] } \ No newline at end of file From 2e9eb98a20a4b544e24648f14c07d87d9441ce70 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 24 Apr 2026 17:12:21 +0800 Subject: [PATCH 16/21] Add a chaincode commitment test Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index 8c3aa330a..bd61a3a29 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -414,6 +414,52 @@ }, "description": "List chaincodes to check if it's been approved" } + }, + { + "name": "Commit the chaincode", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 204\", function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Authorization", + "value": "JWT {{token}}", + "type": "text" + } + ], + "body": {}, + "url": { + "raw": "{{base_url}}/api/v1/chaincodes/{{chaincode_id}}/commit", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "v1", + "chaincodes", + "{{chaincode_id}}", + "commit" + ] + }, + "description": "Commit the chaincode" + } } ], "variable": [ From c165354f9b414defe7818bfd0448ab4f6ba38097 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 24 Apr 2026 17:18:04 +0800 Subject: [PATCH 17/21] Stop the chaincode container Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .github/workflows/integration-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index aa9aa1bd2..79e84c6db 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -30,6 +30,9 @@ jobs: working-directory: tests/postman run: docker compose up --abort-on-container-exit + - name: Stop Hyperledger Fabric Chaincode + run: docker ps -q --filter "name=dev-peer0.org1.foo.com-basic_1.0" | xargs -r docker stop + - name: Stop Hyperledger Fabric Nodes run: docker stop orderer0.foo.com peer0.org1.foo.com From 943c3f473e9b7c93764555b526a33050094fbaf8 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 25 Apr 2026 08:56:56 +0800 Subject: [PATCH 18/21] Get retry times from collection vars rather than envs Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .../Cello Engine CI Test.postman_collection.json | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index bd61a3a29..dfeb26920 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -369,13 +369,15 @@ "let chaincode = json.data.data[0];", "let status = chaincode.status;", "", - "let retries = pm.environment.get(\"retries\");", - "if (status !== \"APPROVED\" && retries < 5) {", - " console.log(`Not ready (status=${status}), retry #${retries}`);", - " pm.environment.set(\"retries\", retries + 1);", - " pm.execution.setNextRequest(\"Wait for the chaincode to be approved\");", - "} else if (retries === 5) {", - " pm.expect.fail(`Max retries reached. Last status: ${status}`);", + "let retries = pm.collectionVariables.get(\"retries\");", + "if (status !== \"APPROVED\") {", + " if (retries < 5) {", + " console.log(`Not ready (status=${status}), retry #${retries}`);", + " pm.collectionVariables.set(\"retries\", retries + 1);", + " pm.execution.setNextRequest(\"Wait for the chaincode to be approved\");", + " } else {", + " pm.expect.fail(`Max retries reached. Last status: ${status}`);", + " }", "}" ], "type": "text/javascript" From e3721b214c49c89c94036a8aabb750846011cde3 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 25 Apr 2026 09:51:50 +0800 Subject: [PATCH 19/21] Increase the retry time upper bound Since the postman delay API only allows clients to delay for at most 10 seconds, the expected 60 seconds delay is unavailable. Thus, the maximum retry time is increased from 5 to 30 to still keep waiting for 5 minutes for the chaincode to be installed and approved. Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- .../Cello Engine CI Test.postman_collection.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index dfeb26920..0b8fec9e4 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -345,13 +345,13 @@ "request": { "method": "GET", "url": { - "raw": "https://postman-echo.com/delay/60", + "raw": "https://postman-echo.com/delay/10", "host": [ "postman-echo.com" ], "path": [ "delay", - "60" + "10" ], "query": [] }, @@ -371,7 +371,7 @@ "", "let retries = pm.collectionVariables.get(\"retries\");", "if (status !== \"APPROVED\") {", - " if (retries < 5) {", + " if (retries < 30) {", " console.log(`Not ready (status=${status}), retry #${retries}`);", " pm.collectionVariables.set(\"retries\", retries + 1);", " pm.execution.setNextRequest(\"Wait for the chaincode to be approved\");", From 476d9bb07ff68b1a4948fa43de9c63e8426c292b Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 25 Apr 2026 18:00:49 +0800 Subject: [PATCH 20/21] Force pulling ccenv before chaincode creation Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- src/agents/hyperledger-fabric/chaincode/service.py | 7 +++++-- src/agents/hyperledger-fabric/node/service.py | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/agents/hyperledger-fabric/chaincode/service.py b/src/agents/hyperledger-fabric/chaincode/service.py index e4afb4432..25a1cf6c2 100644 --- a/src/agents/hyperledger-fabric/chaincode/service.py +++ b/src/agents/hyperledger-fabric/chaincode/service.py @@ -3,14 +3,15 @@ import os import subprocess import tarfile +import docker import yaml from typing import List, Optional, Dict, Any from chaincode.enums import ChaincodeStatus -from hyperledger_fabric.settings import CELLO_HOME, CRYPTO_CONFIG, FABRIC_TOOL +from hyperledger_fabric.settings import CELLO_HOME, CRYPTO_CONFIG, FABRIC_TOOL, FABRIC_VERSION LOG = logging.getLogger(__name__) - +docker_client = docker.DockerClient("unix:///var/run/docker.sock") def get_chaincode_status( package_id: str, @@ -280,6 +281,8 @@ def install_chaincode(file_path: str): ) as f: crypto_config = yaml.safe_load(f) + docker_client.images.pull("hyperledger/fabric-ccenv", tag=FABRIC_VERSION.rsplit(".", 1)[0]) + peer_organization_directory = os.path.join( CELLO_HOME, "peerOrganizations", diff --git a/src/agents/hyperledger-fabric/node/service.py b/src/agents/hyperledger-fabric/node/service.py index f872bbca2..a8eff7480 100644 --- a/src/agents/hyperledger-fabric/node/service.py +++ b/src/agents/hyperledger-fabric/node/service.py @@ -12,8 +12,6 @@ from node.enums import NodeType LOG = logging.getLogger(__name__) - - docker_client = docker.DockerClient("unix:///var/run/docker.sock") def get_node_status(node_type: str, name: str) -> str: From 9adc1fe6d29f5ccc1fa3e0d50e052249583882f1 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sat, 25 Apr 2026 18:10:53 +0800 Subject: [PATCH 21/21] Remove unused variables Signed-off-by: dodo920306 Signed-off-by: khanak0509 --- ...llo Engine CI Test.postman_collection.json | 36 ++----------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/tests/postman/collections/Cello Engine CI Test.postman_collection.json b/tests/postman/collections/Cello Engine CI Test.postman_collection.json index 0b8fec9e4..7aba5ae8c 100644 --- a/tests/postman/collections/Cello Engine CI Test.postman_collection.json +++ b/tests/postman/collections/Cello Engine CI Test.postman_collection.json @@ -13,12 +13,7 @@ "exec": [ "pm.test(\"Status code is 201\", function () {", " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"org_id\", jsonData.data.id);", - "}" + "});" ], "type": "text/javascript" } @@ -107,12 +102,7 @@ "exec": [ "pm.test(\"Status code is 201\", function () {", " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"peer_id\", jsonData.data.id);", - "}" + "});" ], "type": "text/javascript" } @@ -159,12 +149,7 @@ "exec": [ "pm.test(\"Status code is 201\", function () {", " pm.response.to.have.status(201);", - "});", - "", - "if (pm.response.code === 201) {", - " var jsonData = pm.response.json();", - " pm.environment.set(\"orderer_id\", jsonData.data.id);", - "}" + "});" ], "type": "text/javascript" } @@ -475,21 +460,6 @@ "value": "", "type": "string" }, - { - "key": "org_id", - "value": "", - "type": "string" - }, - { - "key": "peer_id", - "value": "", - "type": "string" - }, - { - "key": "orderer_id", - "value": "", - "type": "string" - }, { "key": "channel_id", "value": "",