Skip to content

Commit

Permalink
Add initial alpha testing support (#289)
Browse files Browse the repository at this point in the history
* Add initial alpha testing support

* Update schema for alpha testers and enforce max 10 limit.

* Add alpha release warning.

* Add undefined check.

* Check if alpha app submitted without specifying any testers.

* Update message

* Dont save submission details for alpha app release.

* Print requestId on developer submission window.

---------

Co-authored-by: Ankur Jain <ankur.jain@solana.com>
  • Loading branch information
konoart and ankur2136 authored Jul 31, 2024
1 parent a54f86e commit 932745f
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 14 deletions.
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

0 comments on commit 932745f

Please sign in to comment.