-
Notifications
You must be signed in to change notification settings - Fork 218
Fix theme dev re-authentication #2025
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
Conversation
|
Thanks for your contribution! Depending on what you are working on, you may want to request a review from a Shopify team:
|
Coverage report
Test suite run success1070 tests passing in 564 suites. Report generated by 🧪jest coverage report action from 5343f80 |
b3152ac to
fc0b6b1
Compare
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
| this.execute(adminSession, flags.password, command, controller, false) | ||
| // eslint-disable-next-line @typescript-eslint/no-misused-promises |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been reading about this, but I'm not sure if there's a better way to do this (although it works)...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to make this function async? You're not using the return value of the promise so wouldn't this work as well?
setInterval(() => {
outputDebug('Refreshing theme session tokens...')
refreshTokens(store, flags.password)
}, this.ThemeRefreshTimeoutInMs)
This would give you @typescript-eslint/no-floating-promises, but maybe it's clearer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in fact, we shouldn't use awaits inside setIntervals, it won't work on windows. What @matteodepalo proposed will work 👌
| // Contains token and store to pass to CLI 2.0, which will be set as environment variables | ||
| adminSession?: AdminSession | ||
| // Contains store to pass to CLI 2.0 as environment variable | ||
| store?: string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is a breaking change, but nobody else is using this command 🤷
| } | ||
| async function refreshTokens(store: string, password: string | undefined) { | ||
| const adminSession = await ensureAuthenticatedThemes(store, password, [], true) | ||
| const storefrontToken = await ensureAuthenticatedStorefront([], password, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to forceRefresh the second token. The first one already refreshes the identity token, this second only needs to exchange it.
If you forceRefresh again you are discarding the identity token from the line above.
3c9f219 to
dbb8865
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @gonzaloriestra! Amazing stuff 🔥🚀
This approach is quite clever and it's working well with the standard authentication method (based on the --store flag). The only minor issue I've noticed is that I could not authenticate via Theme Access app.
Other than that minor issue, everything else is excellent 🚀
I fixed the problem. 🎩 it and it's working. Please, could you check it again? |
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationsWe found no new type declarations in this PR Existing type declarationspackages/cli-kit/dist/public/common/version.d.ts@@ -1 +1 @@
-export declare const CLI_KIT_VERSION = "3.46.0";
\ No newline at end of file
+export declare const CLI_KIT_VERSION = "3.46.1";
\ No newline at end of file
packages/cli-kit/dist/public/node/metadata.d.ts@@ -27,7 +27,7 @@ export type SensitiveSchema<T> = T extends RuntimeMetadataManager<infer _TPublic
export declare function createRuntimeMetadataContainer<TPublic extends AnyJson, TSensitive extends AnyJson = {
[key: string]: never;
}>(): RuntimeMetadataManager<TPublic, TSensitive>;
-type CmdFieldsFromMonorail = PickByPrefix<MonorailEventPublic, 'cmd_all_'> & PickByPrefix<MonorailEventPublic, 'cmd_app_'> & PickByPrefix<MonorailEventPublic, 'cmd_create_app_'>;
+type CmdFieldsFromMonorail = PickByPrefix<MonorailEventPublic, 'cmd_all_'> & PickByPrefix<MonorailEventPublic, 'cmd_app_'>;
declare const coreData: RuntimeMetadataManager<CmdFieldsFromMonorail, {
commandStartOptions: {
startTime: number;
packages/cli-kit/dist/public/node/monorail.d.ts@@ -2,7 +2,7 @@ import { JsonMap } from '../../private/common/json.js';
import { DeepRequired } from '../common/ts/deep-required.js';
export { DeepRequired };
type Optional<T> = T | null;
-export declare const MONORAIL_COMMAND_TOPIC: "app_cli3_command/1.4";
+export declare const MONORAIL_COMMAND_TOPIC: "app_cli3_command/1.3";
export interface Schemas {
[MONORAIL_COMMAND_TOPIC]: {
sensitive: {
@@ -51,7 +51,6 @@ export interface Schemas {
cmd_dev_tunnel_type?: Optional<string>;
cmd_dev_tunnel_custom_hash?: Optional<string>;
cmd_dev_urls_updated?: Optional<boolean>;
- cmd_create_app_template?: Optional<string>;
app_extensions_any?: Optional<boolean>;
app_extensions_breakdown?: Optional<string>;
app_extensions_count?: Optional<number>;
packages/cli-kit/dist/public/node/ruby.d.ts@@ -1,11 +1,11 @@
/// <reference types="node" resolution-mode="require"/>
import { AbortSignal } from './abort.js';
-import { AdminSession } from '../../public/node/session.js';
import { Writable } from 'stream';
export declare const RubyCLIVersion = "2.35.0";
export declare const MinWdmWindowsVersion = "0.1.0";
interface ExecCLI2Options {
- adminSession?: AdminSession;
+ store?: string;
+ adminToken?: string;
storefrontToken?: string;
token?: string;
directory?: string;
packages/cli-kit/dist/public/node/session.d.ts@@ -21,9 +21,10 @@ export declare function ensureAuthenticatedPartners(scopes?: string[], _env?: No
*
* @param scopes - Optional array of extra scopes to authenticate with.
* @param password - Optional password to use.
+ * @param forceRefresh - Optional flag to force a refresh of the token.
* @returns The access token for the Storefront API.
*/
-export declare function ensureAuthenticatedStorefront(scopes?: string[], password?: string | undefined): Promise<string>;
+export declare function ensureAuthenticatedStorefront(scopes?: string[], password?: string | undefined, forceRefresh?: boolean): Promise<string>;
/**
* Ensure that we have a valid Admin session for the given store.
*
packages/cli-kit/dist/private/node/session/schema.d.ts@@ -9,13 +9,13 @@ declare const IdentityTokenSchema: zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
+ scopes: string[];
refreshToken: string;
expiresAt: Date;
- scopes: string[];
}, {
accessToken: string;
- refreshToken: string;
scopes: string[];
+ refreshToken: string;
expiresAt?: unknown;
}>;
/**
@@ -27,8 +27,8 @@ declare const ApplicationTokenSchema: zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -55,13 +55,13 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
+ scopes: string[];
refreshToken: string;
expiresAt: Date;
- scopes: string[];
}, {
accessToken: string;
- refreshToken: string;
scopes: string[];
+ refreshToken: string;
expiresAt?: unknown;
}>;
/**
@@ -74,8 +74,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -86,8 +86,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -98,8 +98,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -108,22 +108,22 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
}, "strip", zod.ZodTypeAny, {
identity: {
accessToken: string;
+ scopes: string[];
refreshToken: string;
expiresAt: Date;
- scopes: string[];
};
applications: {} & {
[k: string]: {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
};
};
}, {
identity: {
accessToken: string;
- refreshToken: string;
scopes: string[];
+ refreshToken: string;
expiresAt?: unknown;
};
applications: {} & {
@@ -146,13 +146,13 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
+ scopes: string[];
refreshToken: string;
expiresAt: Date;
- scopes: string[];
}, {
accessToken: string;
- refreshToken: string;
scopes: string[];
+ refreshToken: string;
expiresAt?: unknown;
}>;
/**
@@ -165,8 +165,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -177,8 +177,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -189,8 +189,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -199,22 +199,22 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
}, "strip", zod.ZodTypeAny, {
identity: {
accessToken: string;
+ scopes: string[];
refreshToken: string;
expiresAt: Date;
- scopes: string[];
};
applications: {} & {
[k: string]: {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
};
};
}, {
identity: {
accessToken: string;
- refreshToken: string;
scopes: string[];
+ refreshToken: string;
expiresAt?: unknown;
};
applications: {} & {
@@ -237,13 +237,13 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
+ scopes: string[];
refreshToken: string;
expiresAt: Date;
- scopes: string[];
}, {
accessToken: string;
- refreshToken: string;
scopes: string[];
+ refreshToken: string;
expiresAt?: unknown;
}>;
/**
@@ -256,8 +256,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -268,8 +268,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -280,8 +280,8 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
}, {
accessToken: string;
scopes: string[];
@@ -290,22 +290,22 @@ export declare const SessionSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{
}, "strip", zod.ZodTypeAny, {
identity: {
accessToken: string;
+ scopes: string[];
refreshToken: string;
expiresAt: Date;
- scopes: string[];
};
applications: {} & {
[k: string]: {
accessToken: string;
- expiresAt: Date;
scopes: string[];
+ expiresAt: Date;
};
};
}, {
identity: {
accessToken: string;
- refreshToken: string;
scopes: string[];
+ refreshToken: string;
expiresAt?: unknown;
};
applications: {} & {
|
karreiro
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @alvaro-shopify! It works now — awesome stuff 🚀
WHY are these changes introduced?
Fixes #1843
Fixes #1784
Fixes #1554
The CLI currently restarts the
theme devcommand every ~2 hours to refresh the session, but this is not working very well and it's very annoying for the users because they can lose some job.WHAT is this pull request doing?
Instead of passing the tokens as environment variables to the CLI2 process that runs the server, I let the CLI2 to get them from the CLI2 cache and update that file from the CLI3 every ~2 hours. That way, there's no need to stop the server.
How to test your changes?
ThemeRefreshTimeoutInMsto 1 min (60*1000) in the Dev commandp shopify thme dev --path your-theme --verbosecat ~/.cache/shopify/.db.pstore) and that everything keeps workingMeasuring impact
How do we know this change was effective? Please choose one:
Checklist
devordeployhave been reflected in the internal flowchart.