Skip to content

Commit

Permalink
Fix multichain deploy cid (#2470)
Browse files Browse the repository at this point in the history
* The IPFS CID for multi-chain requires the directory CID.

* The IPFS CID for multi-chain requires the directory CID.

* some change

* unit test

* unit test
  • Loading branch information
yoozo authored Jul 1, 2024
1 parent 37bbe53 commit b7f96c8
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 8 deletions.
3 changes: 3 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- The IPFS CID for multi-chain requires the directory CID.

## [4.15.0] - 2024-06-21
### Changed
- Update `@subql/utils`, `@subql/common` and other dependencies
Expand Down
10 changes: 6 additions & 4 deletions packages/cli/src/commands/multi-chain/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: GPL-3.0

import assert from 'assert';
import fs from 'fs';
import path from 'path';
import {Command, Flags} from '@oclif/core';
Expand All @@ -21,7 +22,7 @@ import {
projectsInfo,
splitMultichainDataFields,
} from '../../controller/deploy-controller';
import {uploadToIpfs} from '../../controller/publish-controller';
import {getDirectoryCid, uploadToIpfs} from '../../controller/publish-controller';
import {MultichainDataFieldType, V3DeploymentIndexerType} from '../../types';
import {addV, checkToken, promptWithDefaultValues, resolveToAbsolutePath, valueOrPrompt} from '../../utils';

Expand Down Expand Up @@ -70,8 +71,9 @@ export default class MultiChainDeploy extends Command {
flags.org = await valueOrPrompt(flags.org, 'Enter organisation', 'Organisation is required');
flags.projectName = await valueOrPrompt(flags.projectName, 'Enter project name', 'Project name is required');

// Multichain query descriptor
const ipfsCID = fileToCidMap.get(path.basename(multichainManifestPath));
// Multichain query descriptor, The IPFS provided for deployment here must be a directory
const ipfsCID = getDirectoryCid(fileToCidMap);
assert(ipfsCID, 'Multichain deployment CID not found');

const projectInfo = await projectsInfo(authToken, flags.org, flags.projectName, ROOT_API_URL_PROD, flags.type);
const chains: V3DeploymentIndexerType[] = [];
Expand Down Expand Up @@ -184,7 +186,7 @@ export default class MultiChainDeploy extends Command {
);
}

this.log('Deploying SubQuery multi-chain project to Hosted Service');
this.log('Deploying SubQuery multi-chain project to Hosted Service, IPFS: ', ipfsCID);

await executeProjectDeployment({
log: this.log.bind(this),
Expand Down
18 changes: 14 additions & 4 deletions packages/cli/src/controller/publish-controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import {promisify} from 'util';
import {mapToObject, ReaderFactory, toJsonObject} from '@subql/common';
import {parseSubstrateProjectManifest} from '@subql/common-substrate';
import rimraf from 'rimraf';
import {createTestProject} from '../createProject.fixtures';
import {uploadToIpfs} from './publish-controller';
import {createMultiChainTestProject, createTestProject} from '../createProject.fixtures';
import {getDirectoryCid, uploadToIpfs} from './publish-controller';

// Replace/Update your access token when test locally
const testAuth = process.env.SUBQL_ACCESS_TOKEN;

jest.setTimeout(300_000); // 300s
describe('Cli publish', () => {
let projectDir: string;

let multiChainProjectDir: string;
let fullPaths: string[];
beforeAll(async () => {
projectDir = await createTestProject();
const res = await Promise.all([createTestProject(), createMultiChainTestProject()]);
projectDir = res[0];
multiChainProjectDir = res[1].multichainManifestPath;
fullPaths = res[1].fullPaths;
});

afterAll(async () => {
Expand Down Expand Up @@ -59,4 +63,10 @@ describe('Cli publish', () => {
});
expect(mapToObject(mockMap)).toStrictEqual({'1': 'aaa', '2': 'bbb'});
});

it('Get directory CID from multi-chain project', async () => {
const cidMap = await uploadToIpfs(fullPaths, testAuth, multiChainProjectDir);
const directoryCid = getDirectoryCid(cidMap);
expect(directoryCid).toBeDefined();
});
});
5 changes: 5 additions & 0 deletions packages/cli/src/controller/publish-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,8 @@ export async function uploadFile(

return cid;
}

export function getDirectoryCid(fileToCidMap: Map<string, string>): string | undefined {
const directoryCid = fileToCidMap.get('');
return directoryCid;
}
48 changes: 48 additions & 0 deletions packages/cli/src/createProject.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import childProcess from 'child_process';
import fs from 'fs';
import os from 'os';
import path from 'path';
import {getMultichainManifestPath, getProjectRootAndManifest} from '@subql/common';
import fetch from 'cross-fetch';
import Build from './commands/build';
import Codegen from './commands/codegen';
Expand All @@ -29,6 +30,24 @@ const projectSpecV1_0_0: ProjectSpecV1_0_0 = {
},
};

const multiProjectSpecV1_0_0: ProjectSpecV1_0_0 = {
name: 'multi_mocked_starter',
chainId: '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3',
endpoint: 'https://arbitrum.llamarpc.com',
author: 'jay',
description: 'this is test for init controller',
runner: {
node: {
name: '@subql/node-ethereum',
version: '>=3.0.0',
},
query: {
name: '@subql/query',
version: '*',
},
},
};

async function getExampleProject(networkFamily: string, network: string): Promise<ExampleProjectInterface | undefined> {
const res = await fetch('https://raw.githubusercontent.com/subquery/templates/main/dist/output.json');

Expand Down Expand Up @@ -62,3 +81,32 @@ export async function createTestProject(): Promise<string> {

return projectDir;
}

export async function createMultiChainTestProject(): Promise<{multichainManifestPath: string; fullPaths: string[]}> {
const tmpdir = await fs.promises.mkdtemp(`${os.tmpdir()}${path.sep}`);
const projectDir = path.join(tmpdir, multiProjectSpecV1_0_0.name);

const exampleProject = await getExampleProject('multi', 'multi');

await cloneProjectTemplate(tmpdir, multiProjectSpecV1_0_0.name, exampleProject);

// Install dependencies
childProcess.execSync(`npm i`, {cwd: projectDir});
// Set test env to be develop mode, only limit to test
process.env.NODE_ENV = 'develop';

await Codegen.run(['-l', projectDir]);
await Build.run(['-f', projectDir]);

const project = getProjectRootAndManifest(projectDir);
const fullPaths = project.manifests.map((manifest) => path.join(project.root, manifest));
let multichainManifestPath = getMultichainManifestPath(projectDir);
if (!multichainManifestPath) {
throw new Error(
'Selected project is not multi-chain. Please set correct file.\n\n https://academy.subquery.network/build/multi-chain.html'
);
}

multichainManifestPath = path.join(project.root, multichainManifestPath);
return {multichainManifestPath, fullPaths};
}

0 comments on commit b7f96c8

Please sign in to comment.