From 42310a6a6d1805e8d40894bf4bced937878b8f67 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:57:30 +0000 Subject: [PATCH 1/7] Initial plan From b4ce44320364baa39ab12b3c45e7efd2e2f1d6db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:04:24 +0000 Subject: [PATCH 2/7] Add MinIO for OSS unit tests Co-authored-by: fengmk2 <156269+fengmk2@users.noreply.github.com> --- .github/workflows/nodejs.yml | 18 +++++++ demo/config.json | 11 ++++ docker-compose.yml | 21 ++++++++ scripts/setup-minio.sh | 48 +++++++++++++++++ test/unit/client/Oss.test.ts | 100 +++++++++++++++++------------------ 5 files changed, 148 insertions(+), 50 deletions(-) create mode 100755 scripts/setup-minio.sh diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 3172109..218dd20 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -36,6 +36,20 @@ jobs: ports: - 2379:2379 - 2380:2380 + minio: + image: minio/minio:latest + env: + MINIO_ROOT_USER: layotto + MINIO_ROOT_PASSWORD: layotto_secret + ports: + - 9000:9000 + - 9001:9001 + options: >- + --health-cmd "curl -f http://localhost:9000/minio/health/live || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + server /data --console-address ":9001" strategy: fail-fast: false @@ -54,6 +68,10 @@ jobs: with: node-version: ${{ matrix.node-version }} + - name: Setup MinIO + run: | + bash scripts/setup-minio.sh + - name: Bootstrap layotto # run: | # cd demo diff --git a/demo/config.json b/demo/config.json index ec049b9..5336c09 100644 --- a/demo/config.json +++ b/demo/config.json @@ -94,6 +94,17 @@ } } }, + "file": { + "oss_demo": { + "type": "minio", + "metadata": { + "endpoint": "localhost:9000", + "accessKeyID": "layotto", + "accessKeySecret": "layotto_secret", + "SSL": false + } + } + }, "app": { "app_id": "app1", "grpc_callback_port": 9999 diff --git a/docker-compose.yml b/docker-compose.yml index 9b917d7..0f5a911 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,8 +23,29 @@ services: networks: - layotto-js-sdk + minio: + image: minio/minio:latest + command: server /data --console-address ":9001" + restart: always + environment: + - MINIO_ROOT_USER=layotto + - MINIO_ROOT_PASSWORD=layotto_secret + ports: + - 9000:9000 + - 9001:9001 + volumes: + - layotto-js-sdk-minio:/data + networks: + - layotto-js-sdk + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 10s + timeout: 5s + retries: 5 + volumes: layotto-js-sdk-redis: + layotto-js-sdk-minio: networks: layotto-js-sdk: diff --git a/scripts/setup-minio.sh b/scripts/setup-minio.sh new file mode 100755 index 0000000..6f2acac --- /dev/null +++ b/scripts/setup-minio.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Setup MinIO for testing +# This script creates the required bucket for OSS tests + +set -e + +# Wait for MinIO to be ready +echo "Waiting for MinIO to be ready..." +for i in {1..30}; do + if curl -sf http://localhost:9000/minio/health/live > /dev/null 2>&1; then + echo "MinIO is ready!" + break + fi + if [ $i -eq 30 ]; then + echo "MinIO failed to start" + exit 1 + fi + echo "Waiting for MinIO... ($i/30)" + sleep 1 +done + +# Install MinIO client if not available +if ! command -v mc &> /dev/null; then + echo "Installing MinIO client..." + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + curl -sSL https://dl.min.io/client/mc/release/linux-amd64/mc -o /tmp/mc + elif [[ "$OSTYPE" == "darwin"* ]]; then + curl -sSL https://dl.min.io/client/mc/release/darwin-amd64/mc -o /tmp/mc + else + echo "Unsupported OS: $OSTYPE" + exit 1 + fi + chmod +x /tmp/mc + MC_CMD="/tmp/mc" +else + MC_CMD="mc" +fi + +# Configure MinIO alias +echo "Configuring MinIO client..." +$MC_CMD alias set myminio http://localhost:9000 layotto layotto_secret + +# Create test bucket +echo "Creating test bucket..." +$MC_CMD mb myminio/layotto-test-bucket --ignore-existing + +echo "MinIO setup complete!" diff --git a/test/unit/client/Oss.test.ts b/test/unit/client/Oss.test.ts index 556ba4d..619ce3f 100644 --- a/test/unit/client/Oss.test.ts +++ b/test/unit/client/Oss.test.ts @@ -6,13 +6,13 @@ import crypto from 'node:crypto'; import { Client } from '../../../src'; import { randomUUID } from 'node:crypto'; -describe.skip('client/Oss.test.ts', () => { +describe('client/Oss.test.ts', () => { const client = new Client('34904', '127.0.0.1', { ossEnable: true }); it('test put object', async () => { const hello = await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test.txt', body: Readable.from(Buffer.from('hello world')), contentLength: 11, @@ -20,7 +20,7 @@ describe.skip('client/Oss.test.ts', () => { assert(hello); const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', // support prefix with `/` key: '/test.txt', }); @@ -36,7 +36,7 @@ describe.skip('client/Oss.test.ts', () => { const fileStream = createReadStream(path.join(__dirname, 'fixtures/empty-file.txt')); const hello = await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test-empty-file.txt', body: fileStream, contentLength: 0, @@ -44,7 +44,7 @@ describe.skip('client/Oss.test.ts', () => { assert(hello); const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test-empty-file.txt', }); const buf: Uint8Array[] = []; @@ -67,7 +67,7 @@ describe.skip('client/Oss.test.ts', () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_large_object.txt', body: Readable.from(buf), contentLength: buf.length, @@ -75,7 +75,7 @@ describe.skip('client/Oss.test.ts', () => { const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_large_object.txt', }); const getHash = crypto.createHash('md5'); @@ -89,17 +89,17 @@ describe.skip('client/Oss.test.ts', () => { it('test copy object', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_copy.txt', body: Readable.from(Buffer.from('hello world')), contentLength: 11, }); const copyRes = await client.oss.copy({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_copy_target.txt', copySource: { - copySourceBucket: 'antsys-tnpmbuild', + copySourceBucket: 'layotto-test-bucket', copySourceKey: 'test_copy.txt', }, }); @@ -107,7 +107,7 @@ describe.skip('client/Oss.test.ts', () => { const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_copy_target.txt', }); @@ -122,21 +122,21 @@ describe.skip('client/Oss.test.ts', () => { it('test delete object', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_delete.txt', body: Readable.from(Buffer.from('hello world')), contentLength: 11, }); const deleteRes = await client.oss.delete({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_delete.txt', }); assert(deleteRes); await assert.rejects(async () => { await client.oss.get({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_delete.txt', }); }, /NoSuchKey/); @@ -145,7 +145,7 @@ describe.skip('client/Oss.test.ts', () => { it('test list object', async () => { const res = await client.oss.list({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', prefix: 'test_', }); assert(res); @@ -155,7 +155,7 @@ describe.skip('client/Oss.test.ts', () => { const ossClient = client.createOSSClient(); const res = await ossClient.list({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', prefix: 'test_', }); assert(res); @@ -165,14 +165,14 @@ describe.skip('client/Oss.test.ts', () => { // Create test objects await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_batch_delete_1.txt', body: Readable.from(Buffer.from('test1')), contentLength: 5, }); await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_batch_delete_2.txt', body: Readable.from(Buffer.from('test2')), contentLength: 5, @@ -181,7 +181,7 @@ describe.skip('client/Oss.test.ts', () => { // Delete multiple objects const deleteRes = await client.oss.deleteObjects({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', objects: [ { key: 'test_batch_delete_1.txt' }, { key: 'test_batch_delete_2.txt' }, @@ -194,7 +194,7 @@ describe.skip('client/Oss.test.ts', () => { it('test isObjectExist', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_exist.txt', body: Readable.from(Buffer.from('exist')), contentLength: 5, @@ -203,7 +203,7 @@ describe.skip('client/Oss.test.ts', () => { // Check existing object const existRes = await client.oss.isObjectExist({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_exist.txt', }); assert.equal(existRes.fileExist, true); @@ -211,7 +211,7 @@ describe.skip('client/Oss.test.ts', () => { // Check non-existing object const notExistRes = await client.oss.isObjectExist({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_not_exist.txt', }); assert.equal(notExistRes.fileExist, false); @@ -220,7 +220,7 @@ describe.skip('client/Oss.test.ts', () => { it('test object tagging', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_tagging.txt', body: Readable.from(Buffer.from('test tagging')), contentLength: 12, @@ -229,7 +229,7 @@ describe.skip('client/Oss.test.ts', () => { // Put tags const putTagRes = await client.oss.putObjectTagging({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_tagging.txt', tags: { env: 'test', @@ -241,7 +241,7 @@ describe.skip('client/Oss.test.ts', () => { // Get tags const getTagRes = await client.oss.getObjectTagging({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_tagging.txt', }); assert(getTagRes.tagsMap); @@ -250,7 +250,7 @@ describe.skip('client/Oss.test.ts', () => { // Delete tags const deleteTagRes = await client.oss.deleteObjectTagging({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_tagging.txt', }); assert(deleteTagRes); @@ -259,7 +259,7 @@ describe.skip('client/Oss.test.ts', () => { it('test object ACL', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_acl.txt', body: Readable.from(Buffer.from('test acl')), contentLength: 8, @@ -268,7 +268,7 @@ describe.skip('client/Oss.test.ts', () => { // Put ACL const putAclRes = await client.oss.putObjectCannedAcl({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_acl.txt', acl: 'private', }); @@ -277,7 +277,7 @@ describe.skip('client/Oss.test.ts', () => { // Get ACL const getAclRes = await client.oss.getObjectCannedAcl({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_acl.txt', }); assert(getAclRes); @@ -288,7 +288,7 @@ describe.skip('client/Oss.test.ts', () => { // Create multipart upload const createRes = await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_multipart.txt', }); assert(createRes.uploadId); @@ -298,7 +298,7 @@ describe.skip('client/Oss.test.ts', () => { const part1Data = Buffer.alloc(1024 * 1024).fill('a'); // 1MB const uploadPart1Res = await client.oss.uploadPart({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_multipart.txt', uploadId, partNumber: 1, @@ -311,7 +311,7 @@ describe.skip('client/Oss.test.ts', () => { const part2Data = Buffer.alloc(1024 * 1024).fill('b'); // 1MB const uploadPart2Res = await client.oss.uploadPart({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_multipart.txt', uploadId, partNumber: 2, @@ -323,7 +323,7 @@ describe.skip('client/Oss.test.ts', () => { // List parts const listPartsRes = await client.oss.listParts({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_multipart.txt', uploadId, }); @@ -333,7 +333,7 @@ describe.skip('client/Oss.test.ts', () => { // Complete multipart upload const completeRes = await client.oss.completeMultipartUpload({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_multipart.txt', uploadId, parts: [ @@ -349,7 +349,7 @@ describe.skip('client/Oss.test.ts', () => { // Create multipart upload const createRes = await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_abort_multipart.txt', }); assert(createRes.uploadId); @@ -359,7 +359,7 @@ describe.skip('client/Oss.test.ts', () => { const partData = Buffer.alloc(1024 * 1024).fill('x'); await client.oss.uploadPart({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_abort_multipart.txt', uploadId, partNumber: 1, @@ -370,7 +370,7 @@ describe.skip('client/Oss.test.ts', () => { // Abort multipart upload const abortRes = await client.oss.abortMultipartUpload({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_abort_multipart.txt', uploadId, }); @@ -381,14 +381,14 @@ describe.skip('client/Oss.test.ts', () => { // Create a multipart upload await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_list_multipart.txt', }); // List multipart uploads const listRes = await client.oss.listMultipartUploads({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', prefix: 'test_list_', }); assert(listRes); @@ -399,7 +399,7 @@ describe.skip('client/Oss.test.ts', () => { // First append const append1Res = await client.oss.appendObject({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key, body: Readable.from(Buffer.from('hello ')), // position: 0, @@ -410,7 +410,7 @@ describe.skip('client/Oss.test.ts', () => { // Second append const append2Res = await client.oss.appendObject({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key, body: Readable.from(Buffer.from('world')), position: nextPosition, @@ -420,7 +420,7 @@ describe.skip('client/Oss.test.ts', () => { // Verify the content const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key, }); const buf: Uint8Array[] = []; @@ -437,7 +437,7 @@ describe.skip('client/Oss.test.ts', () => { const sourceData = Buffer.alloc(2 * 1024 * 1024).fill('s'); // 5MB await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key, body: Readable.from(sourceData), contentLength: sourceData.length, @@ -446,7 +446,7 @@ describe.skip('client/Oss.test.ts', () => { // Create multipart upload for destination const createRes = await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key, }); const uploadId = createRes.uploadId; @@ -454,12 +454,12 @@ describe.skip('client/Oss.test.ts', () => { // Copy part from source const copyPartRes = await client.oss.uploadPartCopy({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key, uploadId, partNumber: 1, copySource: { - copySourceBucket: 'antsys-tnpmbuild', + copySourceBucket: 'layotto-test-bucket', copySourceKey: key, }, }); @@ -469,7 +469,7 @@ describe.skip('client/Oss.test.ts', () => { // Complete multipart upload await client.oss.completeMultipartUpload({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key, uploadId, parts: [ @@ -481,7 +481,7 @@ describe.skip('client/Oss.test.ts', () => { it('test head object', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_head.txt', body: Readable.from(Buffer.from('test head')), contentLength: 9, @@ -489,7 +489,7 @@ describe.skip('client/Oss.test.ts', () => { const headRes = await client.oss.head({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_head.txt', }); assert(headRes); @@ -501,7 +501,7 @@ describe.skip('client/Oss.test.ts', () => { it('test signUrl', async () => { const signRes = await client.oss.signUrl({ storeName: 'oss_demo', - bucket: 'antsys-tnpmbuild', + bucket: 'layotto-test-bucket', key: 'test_sign.txt', method: 'GET', expiredInSec: 3600, From 5f1263bddeeba9965b931e17738754fd1fb2d36b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:06:18 +0000 Subject: [PATCH 3/7] Fix MinIO configuration in GitHub Actions workflow Co-authored-by: fengmk2 <156269+fengmk2@users.noreply.github.com> --- .github/workflows/nodejs.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 218dd20..dd7e080 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -37,19 +37,13 @@ jobs: - 2379:2379 - 2380:2380 minio: - image: minio/minio:latest + image: bitnami/minio:latest env: MINIO_ROOT_USER: layotto MINIO_ROOT_PASSWORD: layotto_secret ports: - 9000:9000 - 9001:9001 - options: >- - --health-cmd "curl -f http://localhost:9000/minio/health/live || exit 1" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - server /data --console-address ":9001" strategy: fail-fast: false From 4fb4df246a6d10d8652695be5c0e1802e3a3bb53 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:07:36 +0000 Subject: [PATCH 4/7] Update README with MinIO setup instructions Co-authored-by: fengmk2 <156269+fengmk2@users.noreply.github.com> --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 672244a..45a36fe 100644 --- a/README.md +++ b/README.md @@ -65,12 +65,18 @@ npm run build:grpc ### step 1. Set up the environment -- Running redis and etcd under Docker +- Running redis, etcd and MinIO under Docker ```bash docker-compose up -d ``` +- Setup MinIO bucket for OSS tests + +```bash +bash scripts/setup-minio.sh +``` + - Start a echoserver for testing the rpc api ```bash From f0f0d828cfe748a9df5b04d576b0dcd533ab9437 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:10:36 +0000 Subject: [PATCH 5/7] Fix shellcheck warning in setup-minio.sh Co-authored-by: fengmk2 <156269+fengmk2@users.noreply.github.com> --- scripts/setup-minio.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup-minio.sh b/scripts/setup-minio.sh index 6f2acac..9e189b5 100755 --- a/scripts/setup-minio.sh +++ b/scripts/setup-minio.sh @@ -12,7 +12,7 @@ for i in {1..30}; do echo "MinIO is ready!" break fi - if [ $i -eq 30 ]; then + if [ "$i" -eq 30 ]; then echo "MinIO failed to start" exit 1 fi From 60a5c9d7fd360fc131f634c89c4981402a28d86e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 05:13:50 +0000 Subject: [PATCH 6/7] Fix CI failure: use official minio/minio image instead of bitnami Co-authored-by: fengmk2 <156269+fengmk2@users.noreply.github.com> --- .github/workflows/nodejs.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index dd7e080..5f026ce 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -36,14 +36,6 @@ jobs: ports: - 2379:2379 - 2380:2380 - minio: - image: bitnami/minio:latest - env: - MINIO_ROOT_USER: layotto - MINIO_ROOT_PASSWORD: layotto_secret - ports: - - 9000:9000 - - 9001:9001 strategy: fail-fast: false @@ -64,6 +56,12 @@ jobs: - name: Setup MinIO run: | + docker run -d \ + --name minio \ + -p 9000:9000 -p 9001:9001 \ + -e MINIO_ROOT_USER=layotto \ + -e MINIO_ROOT_PASSWORD=layotto_secret \ + minio/minio:latest server /data --console-address ":9001" bash scripts/setup-minio.sh - name: Bootstrap layotto From fd3544f09bb892d3a2066299882e0a520751c811 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 12 Nov 2025 05:23:57 +0000 Subject: [PATCH 7/7] Revert bucket name to antsys-tnpmbuild for CI compatibility Co-authored-by: fengmk2 <156269+fengmk2@users.noreply.github.com> --- scripts/setup-minio.sh | 2 +- test/unit/client/Oss.test.ts | 98 ++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/scripts/setup-minio.sh b/scripts/setup-minio.sh index 9e189b5..57d1b49 100755 --- a/scripts/setup-minio.sh +++ b/scripts/setup-minio.sh @@ -43,6 +43,6 @@ $MC_CMD alias set myminio http://localhost:9000 layotto layotto_secret # Create test bucket echo "Creating test bucket..." -$MC_CMD mb myminio/layotto-test-bucket --ignore-existing +$MC_CMD mb myminio/antsys-tnpmbuild --ignore-existing echo "MinIO setup complete!" diff --git a/test/unit/client/Oss.test.ts b/test/unit/client/Oss.test.ts index 619ce3f..308c666 100644 --- a/test/unit/client/Oss.test.ts +++ b/test/unit/client/Oss.test.ts @@ -12,7 +12,7 @@ describe('client/Oss.test.ts', () => { it('test put object', async () => { const hello = await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test.txt', body: Readable.from(Buffer.from('hello world')), contentLength: 11, @@ -20,7 +20,7 @@ describe('client/Oss.test.ts', () => { assert(hello); const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', // support prefix with `/` key: '/test.txt', }); @@ -36,7 +36,7 @@ describe('client/Oss.test.ts', () => { const fileStream = createReadStream(path.join(__dirname, 'fixtures/empty-file.txt')); const hello = await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test-empty-file.txt', body: fileStream, contentLength: 0, @@ -44,7 +44,7 @@ describe('client/Oss.test.ts', () => { assert(hello); const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test-empty-file.txt', }); const buf: Uint8Array[] = []; @@ -67,7 +67,7 @@ describe('client/Oss.test.ts', () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_large_object.txt', body: Readable.from(buf), contentLength: buf.length, @@ -75,7 +75,7 @@ describe('client/Oss.test.ts', () => { const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_large_object.txt', }); const getHash = crypto.createHash('md5'); @@ -89,17 +89,17 @@ describe('client/Oss.test.ts', () => { it('test copy object', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_copy.txt', body: Readable.from(Buffer.from('hello world')), contentLength: 11, }); const copyRes = await client.oss.copy({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_copy_target.txt', copySource: { - copySourceBucket: 'layotto-test-bucket', + copySourceBucket: 'antsys-tnpmbuild', copySourceKey: 'test_copy.txt', }, }); @@ -107,7 +107,7 @@ describe('client/Oss.test.ts', () => { const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_copy_target.txt', }); @@ -122,21 +122,21 @@ describe('client/Oss.test.ts', () => { it('test delete object', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_delete.txt', body: Readable.from(Buffer.from('hello world')), contentLength: 11, }); const deleteRes = await client.oss.delete({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_delete.txt', }); assert(deleteRes); await assert.rejects(async () => { await client.oss.get({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_delete.txt', }); }, /NoSuchKey/); @@ -145,7 +145,7 @@ describe('client/Oss.test.ts', () => { it('test list object', async () => { const res = await client.oss.list({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', prefix: 'test_', }); assert(res); @@ -155,7 +155,7 @@ describe('client/Oss.test.ts', () => { const ossClient = client.createOSSClient(); const res = await ossClient.list({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', prefix: 'test_', }); assert(res); @@ -165,14 +165,14 @@ describe('client/Oss.test.ts', () => { // Create test objects await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_batch_delete_1.txt', body: Readable.from(Buffer.from('test1')), contentLength: 5, }); await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_batch_delete_2.txt', body: Readable.from(Buffer.from('test2')), contentLength: 5, @@ -181,7 +181,7 @@ describe('client/Oss.test.ts', () => { // Delete multiple objects const deleteRes = await client.oss.deleteObjects({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', objects: [ { key: 'test_batch_delete_1.txt' }, { key: 'test_batch_delete_2.txt' }, @@ -194,7 +194,7 @@ describe('client/Oss.test.ts', () => { it('test isObjectExist', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_exist.txt', body: Readable.from(Buffer.from('exist')), contentLength: 5, @@ -203,7 +203,7 @@ describe('client/Oss.test.ts', () => { // Check existing object const existRes = await client.oss.isObjectExist({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_exist.txt', }); assert.equal(existRes.fileExist, true); @@ -211,7 +211,7 @@ describe('client/Oss.test.ts', () => { // Check non-existing object const notExistRes = await client.oss.isObjectExist({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_not_exist.txt', }); assert.equal(notExistRes.fileExist, false); @@ -220,7 +220,7 @@ describe('client/Oss.test.ts', () => { it('test object tagging', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_tagging.txt', body: Readable.from(Buffer.from('test tagging')), contentLength: 12, @@ -229,7 +229,7 @@ describe('client/Oss.test.ts', () => { // Put tags const putTagRes = await client.oss.putObjectTagging({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_tagging.txt', tags: { env: 'test', @@ -241,7 +241,7 @@ describe('client/Oss.test.ts', () => { // Get tags const getTagRes = await client.oss.getObjectTagging({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_tagging.txt', }); assert(getTagRes.tagsMap); @@ -250,7 +250,7 @@ describe('client/Oss.test.ts', () => { // Delete tags const deleteTagRes = await client.oss.deleteObjectTagging({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_tagging.txt', }); assert(deleteTagRes); @@ -259,7 +259,7 @@ describe('client/Oss.test.ts', () => { it('test object ACL', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_acl.txt', body: Readable.from(Buffer.from('test acl')), contentLength: 8, @@ -268,7 +268,7 @@ describe('client/Oss.test.ts', () => { // Put ACL const putAclRes = await client.oss.putObjectCannedAcl({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_acl.txt', acl: 'private', }); @@ -277,7 +277,7 @@ describe('client/Oss.test.ts', () => { // Get ACL const getAclRes = await client.oss.getObjectCannedAcl({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_acl.txt', }); assert(getAclRes); @@ -288,7 +288,7 @@ describe('client/Oss.test.ts', () => { // Create multipart upload const createRes = await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_multipart.txt', }); assert(createRes.uploadId); @@ -298,7 +298,7 @@ describe('client/Oss.test.ts', () => { const part1Data = Buffer.alloc(1024 * 1024).fill('a'); // 1MB const uploadPart1Res = await client.oss.uploadPart({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_multipart.txt', uploadId, partNumber: 1, @@ -311,7 +311,7 @@ describe('client/Oss.test.ts', () => { const part2Data = Buffer.alloc(1024 * 1024).fill('b'); // 1MB const uploadPart2Res = await client.oss.uploadPart({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_multipart.txt', uploadId, partNumber: 2, @@ -323,7 +323,7 @@ describe('client/Oss.test.ts', () => { // List parts const listPartsRes = await client.oss.listParts({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_multipart.txt', uploadId, }); @@ -333,7 +333,7 @@ describe('client/Oss.test.ts', () => { // Complete multipart upload const completeRes = await client.oss.completeMultipartUpload({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_multipart.txt', uploadId, parts: [ @@ -349,7 +349,7 @@ describe('client/Oss.test.ts', () => { // Create multipart upload const createRes = await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_abort_multipart.txt', }); assert(createRes.uploadId); @@ -359,7 +359,7 @@ describe('client/Oss.test.ts', () => { const partData = Buffer.alloc(1024 * 1024).fill('x'); await client.oss.uploadPart({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_abort_multipart.txt', uploadId, partNumber: 1, @@ -370,7 +370,7 @@ describe('client/Oss.test.ts', () => { // Abort multipart upload const abortRes = await client.oss.abortMultipartUpload({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_abort_multipart.txt', uploadId, }); @@ -381,14 +381,14 @@ describe('client/Oss.test.ts', () => { // Create a multipart upload await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_list_multipart.txt', }); // List multipart uploads const listRes = await client.oss.listMultipartUploads({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', prefix: 'test_list_', }); assert(listRes); @@ -399,7 +399,7 @@ describe('client/Oss.test.ts', () => { // First append const append1Res = await client.oss.appendObject({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key, body: Readable.from(Buffer.from('hello ')), // position: 0, @@ -410,7 +410,7 @@ describe('client/Oss.test.ts', () => { // Second append const append2Res = await client.oss.appendObject({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key, body: Readable.from(Buffer.from('world')), position: nextPosition, @@ -420,7 +420,7 @@ describe('client/Oss.test.ts', () => { // Verify the content const res = await client.oss.get({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key, }); const buf: Uint8Array[] = []; @@ -437,7 +437,7 @@ describe('client/Oss.test.ts', () => { const sourceData = Buffer.alloc(2 * 1024 * 1024).fill('s'); // 5MB await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key, body: Readable.from(sourceData), contentLength: sourceData.length, @@ -446,7 +446,7 @@ describe('client/Oss.test.ts', () => { // Create multipart upload for destination const createRes = await client.oss.createMultipartUpload({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key, }); const uploadId = createRes.uploadId; @@ -454,12 +454,12 @@ describe('client/Oss.test.ts', () => { // Copy part from source const copyPartRes = await client.oss.uploadPartCopy({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key, uploadId, partNumber: 1, copySource: { - copySourceBucket: 'layotto-test-bucket', + copySourceBucket: 'antsys-tnpmbuild', copySourceKey: key, }, }); @@ -469,7 +469,7 @@ describe('client/Oss.test.ts', () => { // Complete multipart upload await client.oss.completeMultipartUpload({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key, uploadId, parts: [ @@ -481,7 +481,7 @@ describe('client/Oss.test.ts', () => { it('test head object', async () => { await client.oss.put({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_head.txt', body: Readable.from(Buffer.from('test head')), contentLength: 9, @@ -489,7 +489,7 @@ describe('client/Oss.test.ts', () => { const headRes = await client.oss.head({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_head.txt', }); assert(headRes); @@ -501,7 +501,7 @@ describe('client/Oss.test.ts', () => { it('test signUrl', async () => { const signRes = await client.oss.signUrl({ storeName: 'oss_demo', - bucket: 'layotto-test-bucket', + bucket: 'antsys-tnpmbuild', key: 'test_sign.txt', method: 'GET', expiredInSec: 3600,