Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial alpha testing support #289

Merged
merged 8 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions example/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ release:
solana_mobile_dapp_publisher_portal:
google_store_package: com.solanamobile.cutekitten.gps
testing_instructions: Here are some steps informing Solana Mobile of how to test this dapp. You can specify multiple lines of instructions. For example, if a login is needed, you would add those details here.
alpha_testers:
- address: 3tgkMfug2gs82sy2wexQjMkR12JzFcX9rSLd9yM9m38g
comment: Employe#1 genesis token
- address: G65S4B3RkFpPAt9CwY4cZXptNSkTS6c8hFW1m89GCuB1
comment: Employe#2 genesis token
16 changes: 16 additions & 0 deletions packages/cli/src/CliSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
checkForSelfUpdate,
checkSubmissionNetwork,
Constants,
alphaAppSubmissionMessage,
dryRunSuccessMessage,
generateNetworkSuffix,
parseKeypair,
Expand Down Expand Up @@ -303,6 +304,7 @@ publishCommand
"-d, --dry-run",
"Flag for dry run. Doesn't submit the request to the publisher portal."
)
.option("-l, --alpha", "Flag to mark the submission as alpha test.")
.action(
async ({
appMintAddress,
Expand All @@ -312,6 +314,7 @@ publishCommand
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized,
dryRun,
alpha,
}) => {
await tryWithErrorMessage(async () => {
await checkForSelfUpdate();
Expand All @@ -323,6 +326,10 @@ publishCommand
throw new Error("Either specify a release mint address in the config file or specify as a CLI argument to this command.")
}

if (alpha) {
alphaAppSubmissionMessage()
}

const signer = parseKeypair(keypair);
if (signer) {
if (config.lastUpdatedVersionOnStore != null && config.lastSubmittedVersionOnChain.address != null) {
Expand All @@ -335,6 +342,7 @@ publishCommand
compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
requestorIsAuthorized: requestorIsAuthorized,
critical: false,
alphaTest: alpha,
});
} else {
await publishSubmitCommand({
Expand All @@ -345,6 +353,7 @@ publishCommand
dryRun: dryRun,
compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
requestorIsAuthorized: requestorIsAuthorized,
alphaTest: alpha,
});
}

Expand Down Expand Up @@ -389,6 +398,7 @@ publishCommand
"-d, --dry-run",
"Flag for dry run. Doesn't submit the request to the publisher portal."
)
.option("-l, --alpha", "Flag to mark the submission as alpha test.")
.action(
async ({
appMintAddress,
Expand All @@ -399,6 +409,7 @@ publishCommand
requestorIsAuthorized,
critical,
dryRun,
alpha,
}) => {
await tryWithErrorMessage(async () => {
await checkForSelfUpdate();
Expand All @@ -410,6 +421,10 @@ publishCommand
throw new Error("Either specify a release mint address in the config file or specify as a CLI argument to this command.")
}

if (alpha) {
alphaAppSubmissionMessage()
}

const signer = parseKeypair(keypair);
if (signer) {
await publishUpdateCommand({
Expand All @@ -421,6 +436,7 @@ publishCommand
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized,
critical,
alphaTest: alpha,
});

if (dryRun) {
Expand Down
9 changes: 9 additions & 0 deletions packages/cli/src/CliUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ export const dryRunSuccessMessage = () => {
showMessage("Dry run", "Dry run was successful", "standard")
}

export const alphaAppSubmissionMessage = () => {
showMessage(
"Alpha release",
"Alpha releases are not reviewed on dApp store and are meant for internal testing only.\n" +
"Run the `npx dapp-store publish submit ...` command again without the `--alpha` param to publish the app",
"warning"
)
}

export const showNetworkWarningIfApplicable = (rpcUrl: string) => {
if (isDevnet(rpcUrl)) {
showMessage("Devnet Mode", "Running on Devnet", "warning")
Expand Down
17 changes: 13 additions & 4 deletions packages/cli/src/commands/publish/PublishCliSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type PublishSubmitCommandInput = {
dryRun: boolean;
compliesWithSolanaDappStorePolicies: boolean;
requestorIsAuthorized: boolean;
alphaTest?: boolean;
};

export const publishSubmitCommand = async ({
Expand All @@ -24,6 +25,7 @@ export const publishSubmitCommand = async ({
dryRun = false,
compliesWithSolanaDappStorePolicies = false,
requestorIsAuthorized = false,
alphaTest
}: PublishSubmitCommandInput) => {
showMessage(
`Publishing Estimates`,
Expand Down Expand Up @@ -52,6 +54,10 @@ export const publishSubmitCommand = async ({
lastUpdatedVersionOnStore: lastUpdatedVersionOnStore,
} = await loadPublishDetailsWithChecks();

if (alphaTest && solanaMobileDappPublisherPortalDetails.alpha_testers == undefined) {
throw new Error(`Alpha test submission without specifying any testers.\nAdd field alpha_testers in your 'config.yaml' file.`)
}

const sign = ((buf: Buffer) =>
nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;

Expand All @@ -74,12 +80,15 @@ export const publishSubmitCommand = async ({
solanaMobileDappPublisherPortalDetails,
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized,
alphaTest,
},
dryRun
);

await writeToPublishDetails(
{
lastUpdatedVersionOnStore: { address: releaseAddr }
});
if (!alphaTest) {
await writeToPublishDetails(
{
lastUpdatedVersionOnStore: { address: releaseAddr }
});
}
};
17 changes: 13 additions & 4 deletions packages/cli/src/commands/publish/PublishCliUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type PublishUpdateCommandInput = {
compliesWithSolanaDappStorePolicies: boolean;
requestorIsAuthorized: boolean;
critical: boolean;
alphaTest?: boolean;
};

export const publishUpdateCommand = async ({
Expand All @@ -25,6 +26,7 @@ export const publishUpdateCommand = async ({
compliesWithSolanaDappStorePolicies = false,
requestorIsAuthorized = false,
critical = false,
alphaTest,
}: PublishUpdateCommandInput) => {

showMessage(
Expand Down Expand Up @@ -60,6 +62,10 @@ export const publishUpdateCommand = async ({
lastUpdatedVersionOnStore: lastUpdatedVersionOnStore
} = await loadPublishDetailsWithChecks();

if (alphaTest && solanaMobileDappPublisherPortalDetails.alpha_testers == undefined) {
throw new Error(`Alpha test submission without specifying any testers.\nAdd field alpha_testers in your 'config.yaml' file.`)
}

const sign = ((buf: Buffer) =>
nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;

Expand All @@ -83,11 +89,14 @@ export const publishUpdateCommand = async ({
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized,
criticalUpdate: critical,
alphaTest,
},
dryRun
);
await writeToPublishDetails(
{
lastUpdatedVersionOnStore: { address: releaseAddr }
});
if (!alphaTest) {
await writeToPublishDetails(
{
lastUpdatedVersionOnStore: { address: releaseAddr }
});
}
};
16 changes: 16 additions & 0 deletions packages/cli/src/config/PublishDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import util from "util";
import { imageSize } from "image-size";
import { exec } from "child_process";
import getVideoDimensions from "get-video-dimensions";
import { PublicKey } from "@solana/web3.js";

const runImgSize = util.promisify(imageSize);
const runExec = util.promisify(exec);
Expand Down Expand Up @@ -179,6 +180,21 @@ export const loadPublishDetailsWithChecks = async (
}
}

const alpha_testers = config.solana_mobile_dapp_publisher_portal.alpha_testers;
if (alpha_testers !== undefined) {
for (const wallet of alpha_testers) {
try {
void new PublicKey(wallet.address);
} catch (e: unknown) {
throw new Error(`invalid alpha tester wallet address <${wallet}>`);
}
}

if (alpha_testers.size > 10) {
throw new Error(`Alpha testers are limited to 10 per app submission`);
}
}

return config;
};

Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/prebuild_schema/publishing_source.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,9 @@ release:
solana_mobile_dapp_publisher_portal:
google_store_package: <<ANDROID_PACKAGE_NAME_OF_GOOGLE_PLAY_STORE_VERSION_IF_DIFFERENT>>
testing_instructions: >-
<<TESTING_INSTRUCTIONS>>
<<TESTING_INSTRUCTIONS>>
alpha_testers:
- address: <<genesis token wallet address>>
comment: <<Optional. For internal use only>>
- address: <<genesis token wallet address>>
comment: <<Optional. For internal use only>>
27 changes: 25 additions & 2 deletions packages/core/src/publish/PublishCoreSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
CONTACT_PROPERTY_WEBSITE,
submitRequestToSolanaDappPublisherPortal,
TICKET_OBJECT_ID,
TICKET_PROPERTY_ALPHA_TEST,
TICKET_PROPERTY_ALPHA_TESTERS,
TICKET_PROPERTY_ATTESTATION_PAYLOAD,
TICKET_PROPERTY_AUTHORIZED_REQUEST,
TICKET_PROPERTY_DAPP_COLLECTION_ACCOUNT_ADDRESS,
Expand All @@ -28,7 +30,8 @@ const createSubmitRequest = async (
publisherDetails: Publisher,
solanaMobileDappPublisherPortalDetails: SolanaMobileDappPublisherPortal,
compliesWithSolanaDappStorePolicies: boolean,
requestorIsAuthorized: boolean
requestorIsAuthorized: boolean,
alphaTest?: boolean
) => {
const { attestationPayload, requestUniqueId } = await createAttestationPayload(connection, sign);

Expand Down Expand Up @@ -90,6 +93,14 @@ const createSubmitRequest = async (
});
}

if (alphaTest) {
request.fields.push({
objectTypeId: TICKET_OBJECT_ID,
name: TICKET_PROPERTY_ALPHA_TEST,
value: true,
});
}

if (solanaMobileDappPublisherPortalDetails.testing_instructions !== undefined) {
request.fields.push(
{
Expand All @@ -100,6 +111,14 @@ const createSubmitRequest = async (
);
}

if (solanaMobileDappPublisherPortalDetails.alpha_testers !== undefined && solanaMobileDappPublisherPortalDetails.alpha_testers.length > 0) {
request.fields.push({
objectTypeId: TICKET_OBJECT_ID,
name: TICKET_PROPERTY_ALPHA_TESTERS,
value: solanaMobileDappPublisherPortalDetails.alpha_testers.map(tester => tester.address).toString(),
});
}

return request;
};

Expand All @@ -110,6 +129,7 @@ export type PublishSubmitInput = {
solanaMobileDappPublisherPortalDetails: SolanaMobileDappPublisherPortal;
compliesWithSolanaDappStorePolicies: boolean;
requestorIsAuthorized: boolean;
alphaTest?: boolean;
};

export const publishSubmit = async (
Expand All @@ -121,6 +141,7 @@ export const publishSubmit = async (
solanaMobileDappPublisherPortalDetails,
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized,
alphaTest,
} : PublishSubmitInput,
dryRun: boolean,
) => {
Expand All @@ -132,7 +153,9 @@ export const publishSubmit = async (
publisherDetails,
solanaMobileDappPublisherPortalDetails,
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized);
requestorIsAuthorized,
alphaTest
);

return submitRequestToSolanaDappPublisherPortal(submitRequest, URL_FORM_SUBMIT, dryRun);
};
27 changes: 25 additions & 2 deletions packages/core/src/publish/PublishCoreUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
CONTACT_PROPERTY_WEBSITE,
submitRequestToSolanaDappPublisherPortal,
TICKET_OBJECT_ID,
TICKET_PROPERTY_ALPHA_TEST,
TICKET_PROPERTY_ALPHA_TESTERS,
TICKET_PROPERTY_ATTESTATION_PAYLOAD,
TICKET_PROPERTY_AUTHORIZED_REQUEST,
TICKET_PROPERTY_CRITICAL_UPDATE,
Expand All @@ -29,7 +31,8 @@ const createUpdateRequest = async (
solanaMobileDappPublisherPortalDetails: SolanaMobileDappPublisherPortal,
compliesWithSolanaDappStorePolicies: boolean,
requestorIsAuthorized: boolean,
criticalUpdate: boolean
criticalUpdate: boolean,
alphaTest?: boolean
) => {
const { attestationPayload, requestUniqueId } = await createAttestationPayload(connection, sign);

Expand Down Expand Up @@ -93,6 +96,14 @@ const createUpdateRequest = async (
);
}

if (alphaTest) {
request.fields.push({
objectTypeId: TICKET_OBJECT_ID,
name: TICKET_PROPERTY_ALPHA_TEST,
value: true,
});
}

if (solanaMobileDappPublisherPortalDetails.testing_instructions !== undefined) {
request.fields.push(
{
Expand All @@ -103,6 +114,14 @@ const createUpdateRequest = async (
);
}

if (solanaMobileDappPublisherPortalDetails.alpha_testers !== undefined && solanaMobileDappPublisherPortalDetails.alpha_testers.length > 0) {
request.fields.push({
objectTypeId: TICKET_OBJECT_ID,
name: TICKET_PROPERTY_ALPHA_TESTERS,
value: solanaMobileDappPublisherPortalDetails.alpha_testers.map(tester => tester.address).toString(),
});
}

return request;
};

Expand All @@ -114,6 +133,7 @@ export type PublishUpdateInput = {
compliesWithSolanaDappStorePolicies: boolean;
requestorIsAuthorized: boolean;
criticalUpdate: boolean;
alphaTest?: boolean;
};

export const publishUpdate = async (
Expand All @@ -126,6 +146,7 @@ export const publishUpdate = async (
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized,
criticalUpdate,
alphaTest,
} : PublishUpdateInput,
dryRun: boolean,
) => {
Expand All @@ -138,7 +159,9 @@ export const publishUpdate = async (
solanaMobileDappPublisherPortalDetails,
compliesWithSolanaDappStorePolicies,
requestorIsAuthorized,
criticalUpdate);
criticalUpdate,
alphaTest
);

return submitRequestToSolanaDappPublisherPortal(updateRequest, URL_FORM_UPDATE, dryRun);
};
Loading
Loading