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

feat(cli): cloud cli commands (v4) #20119

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open

Conversation

nathan-pichon
Copy link
Member

@nathan-pichon nathan-pichon commented Apr 15, 2024

What does it do?

This pull request introduces new commands to the Strapi CLI for interacting with Strapi Cloud:

  • strapi login: This command allows users to log in to their Strapi Cloud application directly from the command line.
  • strapi logout: This command enables users to log out of their currently authenticated Strapi Cloud session.
  • strapi deploy: This command provides a streamlined way to deploy the local Strapi project directly to Strapi Cloud.
    These functionalities aim to enhance the developer experience by simplifying authentication and deployment workflows for Strapi Cloud users and providing a seamless hosting solution for Strapi CMS users.

Important Update to create-strapi-app CLI:

Previously, when creating a new Strapi project using create-strapi-app, there was no option to directly connect to a Strapi Cloud project. This pull request also introduces changes to the create-strapi-app command. Users will now be prompted during project creation if they want to create and log in to a new Strapi Cloud project. This simplifies the workflow for developers who intend to deploy their Strapi project to Strapi Cloud from the very beginning.

⚠️ As an MVP restriction, for now, only trial project can be created and managed from the deploy command ⚠️

Why is it needed?

Streamlining deployments: The deploy command automates the deployment process, allowing developers to push their local project to Strapi Cloud directly from the CLI.

How to test it?

  1. Login: Use the strapi login command to authenticate with your Strapi Cloud account. You'll likely be prompted for your credentials during this process (Google / GitHub or GitLab login providers ATM).
  2. Deploy: Ensure you have a local Strapi project ready, you must be able to deploy a trial project (never had any project on Strapi Cloud). Use the strapi deploy command to deploy your project to Strapi Cloud. Verify that the deployment process was completed successfully and your application is accessible on Strapi Cloud.
  3. Logout: User the strapi logout command to disconnect the CLI from your Strapi Cloud account. The strapi deploy should not work after being logged out.

Related issue(s)/PR(s)

Let us know if this is related to any issue/pull request

@nathan-pichon nathan-pichon added source: cli Source is cli package pr: feature This PR adds a new feature echoes/type: feature Effort to deliver new features, significant feature changes and new functionality labels Apr 15, 2024
@nathan-pichon nathan-pichon self-assigned this Apr 15, 2024
@nathan-pichon nathan-pichon changed the title Feat: cloud cli commands (v4) feat(cli): cloud cli commands (v4) Apr 15, 2024
Copy link

vercel bot commented Apr 15, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
contributor-docs ❌ Failed (Inspect) Jun 4, 2024 0:33am

@strapi-cla
Copy link

strapi-cla commented May 30, 2024

CLA assistant check
All committers have signed the CLA.

@nathan-pichon
Copy link
Member Author

A nice improvement would be to add the "deploy" in the generate package.json script so you can run

yarn deploy, & add it in the log at the end of the creation CLI

This will be added in the next iteration.

}
}

export function saveLocalConfig(data: LocalConfig) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can make all the functions async and use a then/catch at the root level anyway.

packages/cli/cloud/src/index.ts Outdated Show resolved Hide resolved
packages/cli/cloud/src/login/action.ts Show resolved Hide resolved
packages/cli/cloud/src/utils/helpers.ts Show resolved Hide resolved
* using a shallow find for the package.json and `fs` to read the file. If no package.json is found,
* the process will throw with an appropriate error message.
*/
const loadPkg = async ({ cwd, logger }: { cwd: string; logger: Logger }): Promise<object> => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping on this before merge

packages/cli/cloud/src/utils/tests/compress-files.test.ts Outdated Show resolved Hide resolved
nathan-pichon and others added 2 commits June 3, 2024 13:02
Co-authored-by: Gonzalo Andres Garcia <nouvellegon@gmail.com>
Co-authored-by: nathan-pichon <nathan.pichon@strapi.io>
Co-authored-by: Abdallah M <55534657+abdallahmz@users.noreply.github.com>
Copy link
Contributor

@innerdvations innerdvations left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though we don't have the infrastructure yet to run them "for real" it would be nice to add some CLI tests that at least verify the commands that exist.

);
return;
case 400:
logger.error('Invalid input. Please check your inputs and try again.');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, or at least I prefer the pattern used for the 403, where you can send a custom message from the cloud API and just fall back on this message.

`Project folder: ${projectFolder}\n`,
`Compressed filename: ${compressedFilename}`
);
await compressFilesToTar(storagePath, projectFolder, compressedFilename);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary, but it would be nice if this could throw as soon as the compressed size exceeded the limit

const fileStats = await fse.stat(tarFilePath);

if (fileStats.size > maxProjectFileSize) {
return ctx.logger.log(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't cleanup the tar file here

packages/cli/cloud/src/login/action.ts Outdated Show resolved Hide resolved
.description('Strapi Cloud Login')
.addHelpText(
'after',
'\nAfter running this command, you will be prompted to enter your authentication information.'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, do we have plans in the future to allow a non-interactive login?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "non-interactive"? Without a Web prompt?

try {
await saveLocalConfig(appConfig);
} catch (error: Error | unknown) {
logger.debug(error);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We supress the error here, but there are places where eraseToken() is called that seem to be expecting it to throw. Should we throw the error rather than logging, and let the caller handle it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like a default try-catch on an awaited promise. I don't think we expected anything while writing eraseToken to be honest 😅

packages/cli/cloud/src/utils/compress-files.ts Outdated Show resolved Hide resolved
}

export async function handleCloudProject(projectName: string): Promise<void> {
let cloudApiService = await cloudServices.cloudApiFactory();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several awaits here that aren't needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? cloudServices.cloudApiFactory() is returning a promise.

Comment on lines +122 to +129
for (const name of keys) {
try {
// Add this command to the Commander command object
strapiCommands[name]({ command, argv, ctx });
await strapiCommands[name]({ command, argv, ctx });
} catch (e) {
console.error(`Failed to load command ${name}`, e);
}
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need building the commands to be async? I think they're all synchronous. But if it still works, I guess it doesn't really matter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StrapiCloudCommands is an async func as we need to use FS, and Alex asked to turn it into async, to generate the deviceId and storing it in user's file system

Co-authored-by: Ben Irvin <ben.irvin@strapi.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
echoes/type: feature Effort to deliver new features, significant feature changes and new functionality pr: feature This PR adds a new feature source: cli Source is cli package
Projects
Status: To be reviewed (Open)
Development

Successfully merging this pull request may close these issues.

None yet

7 participants