Closed avocadoslab closed 1 year ago
I'd like to understand your use case a bit better. Can you expand on why you have development and production apps?
Are you aware that you can test draft versions of your extension on your dev shop?
Yes @catlee, I'm aware that we can test draft version of extension on development store.
When we do local development of an app, you need to have app registered on partner portal in order to install app on development store. So we've created dev app which we use for all testing and validations before pushing new changes to production app.
Dev app is necessary in case where app is using app proxy because you will need different proxy URL while running locally vs while running on production for merchants.
Also in case of embedded app, navigation can vary when we developing a new feature all-together so having that separation is necessary so that live merchants don't see your new navigations.
Hey @catlee :wave: - wanted to jump into this conversation as well and share my perspective.
I'd like to understand your use case a bit better. Can you expand on why you have development and production apps?
Are you aware that you can test draft versions of your extension on your dev shop?
I truly hope this doesn't sound combative, but I'm a little shocked at the idea that one might expect an app to not have multiple instances. No company at any kind of reasonable size is writing code that gets put into a production environment without testing it on (at least) a local instance first.
Most interesting web-based applications have something that exists outside of the Shopify extension world - a server, a database, etc. Any changes to that infrastructure exists outside the versioning system of Shopify extensions and as such having multiple instances is the only way to do safe development work on an app.
Given that multiple app instances are seriously a must, the way these Shopify extensions are registered and updated becomes a workflow problem for developers (like @pratiknikam described, or like @who_khiers
described on Shopify's Discord server).
If theme extensions make API calls to a web server, and that server has a different address based on whether you're in production, staging, local, etc - extensions make it a little difficult to manage. You're either forced to configure app proxies that point back at your different environments for each app instance (and now you're needlessly proxying requests through Shopify), or every single app instance has to have a different URL in its copy of the extension.
It also feels awkward to have to push extension changes for your production app (from an environment that has your production credentials) only to have to go in to the partner dash, make a new extension version and publish it. Not only that, but local development means that all changes to extensions need to be pushed by every developer with a separate app instance using the Shopify CLI. The use of both the CLI and the partner dash to publish the extension makes this feel like a hybrid of automation (i.e. scripting) and manual effort (i.e. pressing buttons in a web interface), which means you get the pains of both and the benefits of neither.
Now all that said, I've just started dabbling with app extensions and it's possible that I'm missing out on some critical elements. If I am, I'm very happy to be told so :smile:
In addition to multiple env files for different apps, we also originally had Ruby env variables in our liquid templates. So, our files had .liquid.erb
extensions. Now, we can't use them within theme-app-extensions
folder.
So, the current workaround we are thinking of is to have a file structure like this:
theme_app_extensions
src
blocks
widget.liquid.erb
...
dist
production
blocks
widget.liquid
.env
staging
blocks
widget.liqud
.env
And a script that will compile files in src
folder multiple times into folders in the dist
folder with different Ruby environments.
.env
files in dist
folder will need to be set up once in the beginning. Then to push to different apps, you will need to go to the corresponding folder in dist
, e.g. theme_app_extensions/dist/production
and run shopify extension push
Thank you @ClaytonPassmore for your feedback, it's really helpful!
I truly hope this doesn't sound combative, but I'm a little shocked at the idea that one might expect an app to not have multiple instances. No company at any kind of reasonable size is writing code that gets put into a production environment without testing it on (at least) a local instance first.
Not combative at all! I fully appreciate the need to have staging/testing environments before pushing code to production. I agree that in this case, having multiple app instances is required since there is no way to have separate backend URLs, etc. for the different environments all represented within a single app.
For now the best workaround I can think of is to manage the .env
files locally for the different environments. This could be achieved manually or via automation scripts similar to what @khier996 has suggested. This is clearly not a great workflow for you, so I will make sure to bring this up as a priority to my team.
The use of both the CLI and the partner dash to publish the extension makes this feel like a hybrid of automation (i.e. scripting) and manual effort (i.e. pressing buttons in a web interface), which means you get the pains of both and the benefits of neither.
Would it help to have CLI support for creating, publishing / unpublishing versions?
Just chiming in, to second most of the views on here. The multiple envs is creating a manual road block to workflows between the lack of env and reliance on manual intervention kinda stifles a fair few of the automated QA and CI pipelines. Really looking forward to more portability with the CLI at present it seems very single developer flow and that is tough in larger teams.
Thanks for the response @catlee! I appreciate you raising the workflow issue with your team.
Would it help to have CLI support for creating, publishing / unpublishing versions?
Yes, that would definitely help! That would (hopefully) allow us to integrate the process of publishing changes into our CD pipeline :+1:
Just came across this as we're a small team experiencing the exact same issue.
Would love to be able to have different versions of a checkout extension for different apps/environments.
Adding the ability to use the shopify-cli in a CI environment would help solve some of these issues. We could use the current recommended setup for local testing. Then when we push to different branches the CI could run the shopify-cli to build and push to shopify for us. The CI could push to different prod and dev apps based on the env vars. At the moment I don't think this is possible due to the fact you can't login to the shopify-cli in a CI environment as the login command needs to open a browser.
Keen to see the extension can connect to multiple apps. We also have local, staging apps for testing/development purpose before releasing new features to prod app. @catlee Do you have a timetable when you are going to finish this feature to enable the extension (post-purchase for our case) to be able to connect to multiple apps?
I too need this as its difficult to switch between environments when testing
+1
+1 I had the same issue with my app
Here's how I solved this:
dist-dev
and dist-prod
folders, depending on whether I type npm run development
vs. npm run production
. These dist folders are Gitignored so they don't get uploaded to version control.dist-dev
and dist-prod
folders is a Shopify-CLI .env file which points to the dev or prod versions of my app, respectively. So, to push the extension to one app or the other, I just have to cd
to the appropriate dist folder and run shopify extension push
. There is no need to rename .env files or log in/out of Shopify CLI.src
files.Thanks for the solution @axis80! Took a lot of inspiration from you can came up with a pretty simple node script that can copy over theme extensions folders and files using recursive-copy and replace-in-file
Was thrown together quickly, so I am sure it could use some clean-up. 🙂
cconst copy = require('recursive-copy');
const replace = require('replace-in-file');
const themeExtensionFolder = 'theme-app-extension';
function buildExtension({ env = 'development' } = {}) {
copy(
`${themeExtensionFolder}/src`,
`${themeExtensionFolder}/${env}`,
{ overwrite: true },
function (error, results) {
if (error) {
console.error('Copy failed: ' + error);
} else {
console.info('Copied ' + results.length + ' files');
if (env === 'production') {
// If production build, assign development variables to production variable values
replaceDevSpecificVars(env);
}
}
}
);
}
async function replaceDevSpecificVars() {
const productionFolderName = 'production';
const replacementPaths = [
`${themeExtensionFolder}/${productionFolderName}/assets/index.js`,
`${themeExtensionFolder}/${productionFolderName}/assets/global.js`,
];
const options = {
files: [...replacementPaths],
from: /PROXY_SUBPATH = 'sale-dev'/g,
to: "PROXY_SUBPATH = 'sale'",
};
try {
const results = await replace(options);
console.log('Replacement results:', results);
} catch (error) {
console.error('Error occurred:', error);
}
}
buildExtension({ env: 'development' });
buildExtension({ env: 'production' });
I created that file in the root of the project and named it copy-theme-extensions.js
, so I could just run node copy-theme-extensions.js
or even add it as a script in package.json
like "build:extension": "node copy-theme-extensions.js"
This is how I solved this issue:
Before following below make sure for each environment such as local, dev and prod apps in your shopify partners page all have a registered app extension. You will need to do this so you have valid credentials for those environments that your primary theme app extension env files can point to.
yarn init
(install yarn if you haven't already).SHOPIFY_API_KEY={{ ENV_API_KEY }}
SHOPIFY_API_SECRET={{ ENV_API_SECRET}}
EXTENSION_TITLE=theme-app-extension
EXTENSION_ID={{ ENV_EXTENSION_ID }}
EXTENSION_UUID={{ ENV_EXTENSION_UUID }}
scripts": {
"publish:dev": "cd theme-app-extension && cp .env.dev .env && shopify extension push && rm .env",
"publish:prod": "cd theme-app-extension && cp .env.prod .env && shopify extension push && rm .env",
"publish:local": "cd theme-app-extension && cp .env.local .env && shopify extension push && rm .env"
}
yarn publish:dev
to push to your desired app.Before following below make sure for each environment such as local, dev and prod apps in your shopify partners page all have a registered app extension. You will need to do this so you have valid credentials for those environments that your primary theme app extension env files can point to.
The biggest challenge we faced connecting apps across environments was registering the app extension for each app (staging app, production app, development apps). This was a challenge because once you run the Shopify CLI command, shopify extension create
, and create the extension for one of your apps you cannot create or register additional apps. A workaround that we used for Theme App Extensions was to rename the Shopify-generated theme-app-extension
directory before running the shopify extension create
command again, which will allow you to create a new app extension attached to a Shopify app (and re-generates the theme-app-extension
directory).
$ mv theme-app-extension theme-app-extension-local
$ shopify extension create
Select the Shopify app to which you would like to connect your extension, such as staging. Then copy your blocks/assets/etc from theme-app-extension-local
to theme-app-extension
.
$ cp -r theme-app-extension-local/blocks theme-app-extension
$ cp -r theme-app-extension-local/assets theme-app-extension
$ cp -r theme-app-extension-local/locales theme-app-extension
$ cp -r theme-app-extension-local/snippets theme-app-extension
Repeat this process for the other apps you would like to register. Once this is done, you can run shopify extension connect
within the theme-app-extension
directory, which will then give you the option to select from any of the apps you have registered and connect to it. You can also remove the various theme-app-extension-*
directories created during this process.
More detailed write up here: https://dev.to/thegnarco/managing-shopify-app-extensions-across-environments-oga
This issue seems inactive. If it's still relevant, please add a comment saying so. Otherwise, take no action.
→ If there's no activity within a week, then a bot will automatically close this.
Thanks for helping to improve Shopify's dev tooling and experience.
As of today, we still have no way of publishing from the CLI - publishing still requires clicking of buttons in a web UI.
That is to say, the problems mentioned in this comment are still relevant.
This is how I solved this issue:
Before following below make sure for each environment such as local, dev and prod apps in your shopify partners page all have a registered app extension. You will need to do this so you have valid credentials for those environments that your primary theme app extension env files can point to.
- Create package json file using command
yarn init
(install yarn if you haven't already).- Create env files for whatever environments you have in my case i just created a dev and prod.
- Copy and past the content of the .env file that gets generated initially and paste it in your new env files with the correct credentials.
SHOPIFY_API_KEY={{ ENV_API_KEY }} SHOPIFY_API_SECRET={{ ENV_API_SECRET}} EXTENSION_TITLE=theme-app-extension EXTENSION_ID={{ ENV_EXTENSION_ID }} EXTENSION_UUID={{ ENV_EXTENSION_UUID }}
- Inside the package.json file add these commands to the scripts tag for each env you would like to publish to. These commands will simply change to the directory where the theme-app-extension is and it will copy the desired env file to .env and push those changes. After that it will delete the .env file that was just generated to clean up.
scripts": { "publish:dev": "cd theme-app-extension && cp .env.dev .env && shopify extension push && rm .env", "publish:prod": "cd theme-app-extension && cp .env.prod .env && shopify extension push && rm .env", "publish:local": "cd theme-app-extension && cp .env.local .env && shopify extension push && rm .env" }
- In the root folder of your directory where the theme-app-extension lies simply run one of the commands such as
yarn publish:dev
to push to your desired app.
This best way to manage the env @ElishaStaks Thanks lot's
+1
Considering my experience with Shopify developer support so far, I wouldn't bank on this feature being added any time soon.
This issue seems inactive. If it's still relevant, please add a comment saying so. Otherwise, take no action.
→ If there's no activity within a week, then a bot will automatically close this.
Thanks for helping to improve Shopify's dev tooling and experience.
This issue is still relevant.
Very relevant, @shopify-admins have yet to comment. Please provide an update rather than being silent.
A very simple solution that worked for me.
Always run npm run deploy -- --reset
to deploy the theme app.
This allows you to choose to which app you want to connect and deploy the app extension to.
This DOES NOT change the saved config for the npm run dev
command, which means that when you run npm run dev
, app extension gets pushed to the development app only.
@AdityaMalani you are a star!
This fixes the issue https://github.com/Shopify/cli/issues/1998 sometimes may need to change env by running this command:
export SHOPIFY_API_KEY='your key'
We've solved the issue on our end as follows:
shopify deploy
dist
and exchanges environment dependent variables in the codeThere's a .env
file with each environment variable to be replaced.
{
"config": {
"API_KEY_PROD": "ABC", // replace with your API key
"API_KEY_DEV": "DEF" // replace with your API key
},
"scripts": {
"shopify:ext:prepare": "node extensions/prepare.mjs",
"shopify:ext:cleanup": "node extensions/cleanup.mjs",
"shopify:deploy:run": "shopify app deploy --force",
"shopify:deploy:prod": "yarn shopify:ext:prepare prod && yarn shopify:deploy:run --api-key=$npm_package_config_API_KEY_PROD && yarn shopify:ext:cleanup",
"shopify:deploy:dev": "yarn shopify:ext:prepare dev && yarn shopify:deploy:run --api-key=$npm_package_config_API_KEY_DEV && yarn shopify:ext:cleanup"
},
"devDependencies": {
"@shopify/app": "^3.45.4",
"@shopify/cli": "^3.45.4"
}
}
import { execSync } from 'child_process';
import { config } from 'dotenv';
import { readFileSync, writeFileSync } from 'fs';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const _dirname = dirname(fileURLToPath(import.meta.url));
const environment = process.argv[2];
if (environment === 'dev') {
config({ path: `${_dirname}/.env.development` });
} else if (environment === 'prod') {
config({ path: `${_dirname}/.env` });
} else {
throw new Error(`Unknown env ${environment}`);
}
// copy all files from current directory into dist
const distPath = `${_dirname}/dist`;
const shell = execSync;
shell(`rm -rf ${distPath}`);
shell(`cp -r ${_dirname} ${distPath}`);
// read file and replace ENV Var
const filePath = `${distPath}/widget-ext/blocks/widget-embed.liquid`;
const buf = readFileSync(filePath);
const fileString = buf.toString();
const newString = fileString.replace('$_{MY_ENV_VAR}', process.env.MY_ENV_VAR);
writeFileSync(filePath, newString);
import { execSync } from 'child_process';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const _dirname = dirname(fileURLToPath(import.meta.url));
// copy all files from current directory into dist
const distPath = `${_dirname}/dist`;
const shell = execSync;
shell(`rm -rf ${distPath}`);
extension_directories = ["extensions/dist/*"]
This issue seems inactive. If it's still relevant, please add a comment saying so. Otherwise, take no action. → If there's no activity within a week, then a bot will automatically close this. Thanks for helping to improve Shopify's dev tooling and experience.
P.S. You can learn more about why we stale issues here.
Hi All from 31 may 2023 Shopify CLI 2.x was sunset I will suggest to use Shopify CLI 3.x it was very easy to connect multiple theme app extension.
https://github.com/Shopify/shopify-app-template-node/blob/main/package.json
` npm run npm run dev -- --reset # rest shopify account
npm run info
"scripts": { "shopify": "shopify", "build": "shopify app build", "dev": "shopify app dev", "info": "shopify app info", "generate": "shopify app generate", "deploy": "shopify app deploy" }, `
This issue seems inactive. If it's still relevant, please add a comment saying so. Otherwise, take no action. → If there's no activity within a week, then a bot will automatically close this. Thanks for helping to improve Shopify's dev tooling and experience.
P.S. You can learn more about why we stale issues here.
If we're learning to live with it, does that make it inactive? Think on it, @github-actions bot and let me know what you come up with.
@all please use the Shopify Cli 3.0
"@shopify/app": "^3.47.5", "@shopify/cli": "^3.47.5", "@shopify/cli-kit": "^3.47.5",
it was wasy to connect same "theme app extension " to many app just you need to --reset and select app.
it was really good. Thanks to shopify team @shopify-admins
Hey folks, we've recently released 3.48.0
which includes support for connecting your source to multiple apps. Check out the documentation here:
The CLI also supports creating a live version with app deploy
and an unreleased version with app deploy --no-release
. You can read more about simplified deployments here: https://shopify.dev/docs/apps/deployment/extension/simplified
I'm going to close this, but feel free to open new issues. Thanks for reporting and for your patience!
Issue summary
shopify extension create
allows extension to be created and connected to one Shopify app. In cases where you have development app and production app, how do we connect or register same extension with both apps?shopify extension connect
allows connecting only to previously selected development app so would love to know how to handle this case.Expected behavior
As a developer, I should have flexibility of connecting/registering extension to more than one app in cases where we maintain development, staging & production app.
Actual behavior
Can't register already registered extension to new app.