in pkg/php/php.go [153:227]
func ComposerInstall(ctx *gcp.Context, cacheTag string) (*libcnb.Layer, error) {
var flags []string
if composerArgs := os.Getenv(ComposerArgsEnv); composerArgs != "" {
flags = strings.Split(composerArgs, " ")
} else {
// We don't install dev dependencies (i.e. we pass --no-dev to composer) because doing so has caused
// problems for customers in the past. For more information see these links:
// https://github.com/GoogleCloudPlatform/php-docs-samples/issues/736
// https://github.com/GoogleCloudPlatform/runtimes-common/pull/763
// https://github.com/GoogleCloudPlatform/runtimes-common/commit/6c4970f609d80f9436ac58ae272cfcc6bcd57143
flags = []string{"--no-dev", "--no-progress", "--no-interaction", "--optimize-autoloader"}
}
if err := ctx.RemoveAll(Vendor); err != nil {
return nil, err
}
l, err := ctx.Layer("composer", gcp.CacheLayer)
if err != nil {
return nil, fmt.Errorf("creating layer: %w", err)
}
layerVendor := filepath.Join(l.Path, Vendor)
composerLockExists, err := ctx.FileExists(composerLock)
if err != nil {
return nil, err
}
// If there's no composer.lock then don't attempt to cache. We'd have to cache using composer.json,
// which could result in outdated dependencies if the version constraints in composer.json resolve
// to newer versions in the future.
if !composerLockExists {
ctx.Logf("*** Improve build performance by generating and committing %s.", composerLock)
if err := composerInstall(ctx, flags); err != nil {
return nil, err
}
return l, nil
}
currentPHPVersion, err := version(ctx)
if err != nil {
return nil, err
}
hash, cached, err := cache.HashAndCheck(ctx, l, dependencyHashKey, cache.WithFiles(composerJSON, composerLock), cache.WithStrings(currentPHPVersion))
if err != nil {
return nil, err
}
if cached {
// PHP expects the vendor/ directory to be in the application directory.
if _, err := ctx.Exec([]string{"cp", "--archive", layerVendor, Vendor}, gcp.WithUserTimingAttribution); err != nil {
return nil, err
}
} else {
ctx.Logf("Installing application dependencies.")
// Clear layer so we don't end up with outdated dependencies (e.g. something was removed from composer.json).
if err := ctx.ClearLayer(l); err != nil {
return nil, fmt.Errorf("clearing layer %q: %w", l.Name, err)
}
if err := composerInstall(ctx, flags); err != nil {
return nil, err
}
// Update the layer metadata.
cache.Add(ctx, l, dependencyHashKey, hash)
// Ensure vendor exists even if no dependencies were installed.
if err := ctx.MkdirAll(Vendor, 0755); err != nil {
return nil, err
}
if _, err := ctx.Exec([]string{"cp", "--archive", Vendor, layerVendor}, gcp.WithUserTimingAttribution); err != nil {
return nil, err
}
}
return l, nil
}