in cli/azd/cmd/init.go [157:379]
func (i *initAction) Run(ctx context.Context) (*actions.ActionResult, error) {
wd, err := os.Getwd()
if err != nil {
return nil, fmt.Errorf("getting cwd: %w", err)
}
azdCtx := azdcontext.NewAzdContextWithDirectory(wd)
i.lazyAzdCtx.SetValue(azdCtx)
if i.flags.templateBranch != "" && i.flags.templatePath == "" {
return nil,
errors.New(
"using branch argument (-b or --branch) requires a template argument (--template or -t) to be specified")
}
// ensure that git is available
if err := tools.EnsureInstalled(ctx, []tools.ExternalTool{i.gitCli}...); err != nil {
return nil, err
}
// Command title
i.console.MessageUxItem(ctx, &ux.MessageTitle{
Title: "Initializing an app to run on Azure (azd init)",
})
// AZD supports having .env at the root of the project directory as the initial environment file.
// godotenv.Load() -> add all the values from the .env file in the process environment
// If AZURE_ENV_NAME is set in the .env file, it will be used to name the environment during env initialize.
if err := godotenv.Overload(); err != nil {
// ignore the error if the file does not exist
if !os.IsNotExist(err) {
return nil, fmt.Errorf("reading .env file: %w", err)
}
}
if i.flags.EnvFlag.EnvironmentName == "" ||
(i.flags.EnvFlag.EnvironmentName != "" && !i.flags.EnvFlag.FromArg()) {
// only azd init supports using .env to influence the command. The `-e` flag is linked to the
// env var AZURE_ENV_NAME, which means it could've be set either from ENV or from arg.
// re-setting the value here after loading the .env file overrides any value coming from the system env but
// doest not override the value coming from the arg.
i.flags.EnvFlag.EnvironmentName = os.Getenv(environment.EnvNameEnvVarName)
}
var existingProject bool
if _, err := os.Stat(azdCtx.ProjectPath()); err == nil {
existingProject = true
} else if errors.Is(err, os.ErrNotExist) {
existingProject = false
} else {
return nil, fmt.Errorf("checking if project exists: %w", err)
}
var initTypeSelect initType
if i.flags.templatePath != "" || len(i.flags.templateTags) > 0 {
// an explicit --template passed, always initialize from app template
initTypeSelect = initAppTemplate
}
if i.flags.fromCode {
if i.flags.templatePath != "" {
return nil, errors.New("only one of init modes: --template, or --from-code should be set")
}
initTypeSelect = initFromApp
}
if i.flags.templatePath == "" && !i.flags.fromCode && existingProject {
// only initialize environment when no mode is set explicitly
initTypeSelect = initEnvironment
}
if initTypeSelect == initUnknown {
initTypeSelect, err = promptInitType(i.console, ctx)
if err != nil {
return nil, err
}
}
header := "New project initialized!"
followUp := heredoc.Docf(`
You can view the template code in your directory: %s
Learn more about running 3rd party code on our DevHub: %s`,
output.WithLinkFormat("%s", wd),
output.WithLinkFormat("%s", "https://aka.ms/azd-third-party-code-notice"))
switch initTypeSelect {
case initAppTemplate:
tracing.SetUsageAttributes(fields.InitMethod.String("template"))
template, err := i.initializeTemplate(ctx, azdCtx)
if err != nil {
return nil, err
}
if _, err := i.initializeEnv(ctx, azdCtx, template.Metadata); err != nil {
return nil, err
}
if i.flags.up {
// Prompt to deploy to Azure
deploy, err := i.console.Confirm(ctx, input.ConsoleOptions{
Message: "Do you want to run " + output.WithHighLightFormat("azd up") + " now?",
DefaultValue: true,
Help: "Template files have been initialized in your local directory. " +
"If you want to provision and deploy now without making changes, select Y. If not, select N.",
})
if err != nil {
return nil, err
}
if deploy {
// Call azd up
startTime := time.Now()
i.azd.SetArgs([]string{"up", "--cwd", azdCtx.ProjectDirectory()})
err := i.azd.ExecuteContext(ctx)
header = "New project initialized! Provision and deploy to Azure was completed in " +
ux.DurationAsText(since(startTime)) + "."
if err != nil {
return nil, err
}
}
}
case initFromApp:
tracing.SetUsageAttributes(fields.InitMethod.String("app"))
header = "Your app is ready for the cloud!"
followUp = "You can provision and deploy your app to Azure by running the " + output.WithHighLightFormat("azd up") +
" command in this directory. For more information on configuring your app, see " +
output.WithHighLightFormat("./next-steps.md")
entries, err := os.ReadDir(azdCtx.ProjectDirectory())
if err != nil {
return nil, fmt.Errorf("reading current directory: %w", err)
}
if len(entries) == 0 {
return nil, &internal.ErrorWithSuggestion{
Err: errors.New("no files found in the current directory"),
Suggestion: "Ensure you're in the directory where your app code is located and try again." +
" If you do not have code and would like to start with an app template, run '" +
output.WithHighLightFormat("azd init") + "' and select the option to " +
color.MagentaString("Use a template") + ".",
}
}
err = i.repoInitializer.InitFromApp(ctx, azdCtx, func() (*environment.Environment, error) {
return i.initializeEnv(ctx, azdCtx, templates.Metadata{})
})
if err != nil {
return nil, err
}
case initEnvironment:
env, err := i.initializeEnv(ctx, azdCtx, templates.Metadata{})
if err != nil {
return nil, err
}
header = fmt.Sprintf("Initialized environment %s.", env.Name())
followUp = ""
case initProject:
tracing.SetUsageAttributes(fields.InitMethod.String("project"))
composeAlphaEnabled := i.featuresManager.IsEnabled(composeFeature)
if !composeAlphaEnabled {
err = i.repoInitializer.InitializeMinimal(ctx, azdCtx)
if err != nil {
return nil, err
}
_, err := i.initializeEnv(ctx, azdCtx, templates.Metadata{})
if err != nil {
return nil, err
}
followUp = ""
} else {
fi, err := os.Stat(azdCtx.ProjectPath())
if err != nil && !errors.Is(err, os.ErrNotExist) {
return nil, err
}
if fi != nil {
return nil, fmt.Errorf("project already initialized")
}
name, err := i.console.Prompt(ctx, input.ConsoleOptions{
Message: "What is the name of your project?",
DefaultValue: azdcontext.ProjectName(azdCtx.ProjectDirectory()),
})
if err != nil {
return nil, err
}
prjConfig := project.ProjectConfig{
Name: name,
}
if composeAlphaEnabled {
prjConfig.MetaSchemaVersion = "alpha"
}
err = project.Save(ctx, &prjConfig, azdCtx.ProjectPath())
if err != nil {
return nil, fmt.Errorf("saving project config: %w", err)
}
followUp = "Run " + output.WithHighLightFormat("azd add") + " to add new Azure components to your project."
}
header = "Generated azure.yaml project file."
default:
panic("unhandled init type")
}
if err := i.initializeExtensions(ctx, azdCtx); err != nil {
return nil, fmt.Errorf("initializing project extensions: %w", err)
}
return &actions.ActionResult{
Message: &actions.ResultMessage{
Header: header,
FollowUp: followUp,
},
}, nil
}