mirror of
https://github.com/hanzoai/pack.git
synced 2026-09-30 23:43:13 +00:00
Merge pull request #33 from railwayapp/jr/step-inputs-and-deploy-step
Step inputs and deploy step
This commit is contained in:
+120
-115
@@ -8,6 +8,7 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/moby/buildkit/client/llb"
|
||||
"github.com/moby/buildkit/util/system"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@@ -17,7 +18,6 @@ import (
|
||||
|
||||
type BuildGraph struct {
|
||||
graph *graph.Graph
|
||||
BaseState *llb.State
|
||||
CacheStore *BuildKitCacheStore
|
||||
Plan *plan.BuildPlan
|
||||
Platform *specs.Platform
|
||||
@@ -32,7 +32,7 @@ type BuildGraphOutput struct {
|
||||
GraphEnv BuildEnvironment
|
||||
}
|
||||
|
||||
func NewBuildGraph(plan *plan.BuildPlan, baseState *llb.State, localState *llb.State, cacheStore *BuildKitCacheStore, secretsHash string, platform *specs.Platform) (*BuildGraph, error) {
|
||||
func NewBuildGraph(plan *plan.BuildPlan, localState *llb.State, cacheStore *BuildKitCacheStore, secretsHash string, platform *specs.Platform) (*BuildGraph, error) {
|
||||
var secretsFile *llb.State
|
||||
if secretsHash != "" {
|
||||
st := llb.Scratch().File(llb.Mkfile("/secrets-hash", 0644, []byte(secretsHash)), llb.WithCustomName("[railpack] secrets hash"))
|
||||
@@ -42,7 +42,6 @@ func NewBuildGraph(plan *plan.BuildPlan, baseState *llb.State, localState *llb.S
|
||||
|
||||
g := &BuildGraph{
|
||||
graph: graph.NewGraph(),
|
||||
BaseState: baseState,
|
||||
CacheStore: cacheStore,
|
||||
Plan: plan,
|
||||
Platform: platform,
|
||||
@@ -67,23 +66,124 @@ func NewBuildGraph(plan *plan.BuildPlan, baseState *llb.State, localState *llb.S
|
||||
// Add dependencies to each node
|
||||
for _, node := range g.graph.GetNodes() {
|
||||
llbNode := node.(*StepNode)
|
||||
for _, depName := range llbNode.Step.DependsOn {
|
||||
if depNode, exists := g.graph.GetNode(depName); exists {
|
||||
for _, input := range llbNode.Step.Inputs {
|
||||
// This input does not reference another step
|
||||
if input.Step == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if depNode, exists := g.graph.GetNode(input.Step); exists {
|
||||
// Create edges between the current node and the dependency node
|
||||
parents := llbNode.GetParents()
|
||||
parents = append(parents, depNode)
|
||||
llbNode.SetParents(parents)
|
||||
|
||||
children := depNode.GetChildren()
|
||||
children = append(children, node)
|
||||
children = append(children, llbNode)
|
||||
depNode.SetChildren(children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g.graph.ComputeTransitiveDependencies()
|
||||
|
||||
// g.graph.PrintGraph()
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *BuildGraph) GetStateForInput(input plan.Input, baseState llb.State) llb.State {
|
||||
var state llb.State
|
||||
|
||||
if input.Image != "" {
|
||||
state = llb.Image(input.Image, llb.Platform(*g.Platform))
|
||||
} else if input.Local {
|
||||
state = *g.LocalState
|
||||
} else if input.Step != "" {
|
||||
if node, exists := g.graph.GetNode(input.Step); exists {
|
||||
nodeState := node.(*StepNode).State
|
||||
if nodeState == nil {
|
||||
return baseState
|
||||
}
|
||||
state = *nodeState
|
||||
}
|
||||
} else {
|
||||
state = baseState
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func (g *BuildGraph) GetFullStateFromInputs(inputs []plan.Input) llb.State {
|
||||
if len(inputs) == 0 {
|
||||
return llb.Scratch()
|
||||
}
|
||||
|
||||
if len(inputs[0].Include)+len(inputs[0].Exclude) > 0 {
|
||||
panic("first input must not have include or exclude paths")
|
||||
}
|
||||
|
||||
// Get the base state from the first input
|
||||
state := g.GetStateForInput(inputs[0], llb.Scratch())
|
||||
if len(inputs) == 1 {
|
||||
return state
|
||||
}
|
||||
|
||||
// Copy from subsequent inputs into the base state
|
||||
for _, input := range inputs[1:] {
|
||||
inputState := g.GetStateForInput(input, llb.Scratch())
|
||||
|
||||
// Copy the specified paths (or everything) from this input into our base state
|
||||
if len(input.Include) > 0 {
|
||||
for _, include := range input.Include {
|
||||
if input.Local {
|
||||
// For local context, always copy into /app
|
||||
destPath := filepath.Join("/app", filepath.Base(include))
|
||||
state = state.File(llb.Copy(inputState, include, destPath, &llb.CopyInfo{
|
||||
CopyDirContentsOnly: true,
|
||||
CreateDestPath: true,
|
||||
FollowSymlinks: true,
|
||||
AllowWildcard: true,
|
||||
AllowEmptyWildcard: true,
|
||||
ExcludePatterns: input.Exclude,
|
||||
}))
|
||||
} else {
|
||||
// For other states, handle paths based on whether they're absolute or relative
|
||||
srcPath := include
|
||||
var destPath string
|
||||
|
||||
switch {
|
||||
case include == "." || include == "/app" || include == "/app/":
|
||||
// Copy entire /app directory
|
||||
srcPath = "/app"
|
||||
destPath = "/app"
|
||||
case filepath.IsAbs(include):
|
||||
// Preserve absolute paths exactly
|
||||
destPath = include
|
||||
default:
|
||||
// Relative paths are relative to /app
|
||||
srcPath = filepath.Join("/app", include)
|
||||
destPath = filepath.Join("/app", include)
|
||||
}
|
||||
|
||||
state = state.File(llb.Copy(inputState, srcPath, destPath, &llb.CopyInfo{
|
||||
CopyDirContentsOnly: true,
|
||||
CreateDestPath: true,
|
||||
FollowSymlinks: true,
|
||||
AllowWildcard: true,
|
||||
AllowEmptyWildcard: true,
|
||||
ExcludePatterns: input.Exclude,
|
||||
}))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Warnf("input %s has no include or exclude paths. This is probably a mistake.", input.Step)
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
// GenerateLLB generates the LLB state for the build graph
|
||||
func (g *BuildGraph) GenerateLLB() (*BuildGraphOutput, error) {
|
||||
// Get processing order using topological sort
|
||||
@@ -100,74 +200,22 @@ func (g *BuildGraph) GenerateLLB() (*BuildGraphOutput, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Find all leaf nodes and get their states
|
||||
var leafNodes []*StepNode
|
||||
graphEnv := NewGraphEnvironment()
|
||||
// Process deploy state
|
||||
deployState := g.GetFullStateFromInputs(g.Plan.Deploy.Inputs)
|
||||
|
||||
for _, node := range g.graph.GetNodes() {
|
||||
llbNode := node.(*StepNode)
|
||||
if len(llbNode.GetChildren()) == 0 && llbNode.State != nil {
|
||||
leafNodes = append(leafNodes, llbNode)
|
||||
graphEnv.Merge(llbNode.OutputEnv)
|
||||
graphEnv := NewGraphEnvironment()
|
||||
for _, input := range g.Plan.Deploy.Inputs {
|
||||
if node, exists := g.graph.GetNode(input.Step); exists {
|
||||
graphEnv.Merge(node.(*StepNode).OutputEnv)
|
||||
}
|
||||
}
|
||||
|
||||
// If no leaf states, return base state
|
||||
if len(leafNodes) == 0 {
|
||||
return &BuildGraphOutput{
|
||||
State: g.BaseState,
|
||||
GraphEnv: graphEnv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// If only one leaf state, return it
|
||||
if len(leafNodes) == 1 {
|
||||
return &BuildGraphOutput{
|
||||
State: leafNodes[0].State,
|
||||
GraphEnv: graphEnv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
result := g.mergeNodes(leafNodes)
|
||||
|
||||
return &BuildGraphOutput{
|
||||
State: &result,
|
||||
State: &deployState,
|
||||
GraphEnv: graphEnv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// mergeNodes merges the states of the given nodes into a single state
|
||||
// This essentially creates a scratch file system and then copies the contents of each node's state into it
|
||||
func (g *BuildGraph) mergeNodes(nodes []*StepNode) llb.State {
|
||||
if len(nodes) == 1 {
|
||||
return *nodes[0].State
|
||||
}
|
||||
|
||||
// Sort nodes by step name for deterministic ordering
|
||||
sortedNodes := slices.Clone(nodes)
|
||||
slices.SortFunc(sortedNodes, func(a, b *StepNode) int {
|
||||
return strings.Compare(a.Step.Name, b.Step.Name)
|
||||
})
|
||||
|
||||
stateNames := []string{}
|
||||
states := []llb.State{}
|
||||
for _, node := range sortedNodes {
|
||||
stateNames = append(stateNames, node.Step.Name)
|
||||
states = append(states, *node.State)
|
||||
}
|
||||
|
||||
result := llb.Scratch()
|
||||
for i, state := range states {
|
||||
result = result.File(llb.Copy(state, "/", "/", &llb.CopyInfo{
|
||||
CreateDestPath: true,
|
||||
FollowSymlinks: true,
|
||||
AllowWildcard: true,
|
||||
}), llb.WithCustomNamef("copy from %s", stateNames[i]))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// processNode processes a node and its parents to determine the state to build upon
|
||||
func (g *BuildGraph) processNode(node *StepNode) error {
|
||||
// If already processed, we're done
|
||||
@@ -196,7 +244,7 @@ func (g *BuildGraph) processNode(node *StepNode) error {
|
||||
}
|
||||
|
||||
// Determine the state to build upon
|
||||
var currentState *llb.State
|
||||
// var currentState llb.State
|
||||
currentGraphEnv := NewGraphEnvironment()
|
||||
|
||||
// Merge the output envs of all the parent nodes
|
||||
@@ -205,29 +253,10 @@ func (g *BuildGraph) processNode(node *StepNode) error {
|
||||
currentGraphEnv.Merge(parentNode.OutputEnv)
|
||||
}
|
||||
|
||||
if len(node.GetParents()) == 0 {
|
||||
currentState = g.BaseState
|
||||
} else {
|
||||
parentNodes := make([]*StepNode, len(node.GetParents()))
|
||||
for i, parent := range node.GetParents() {
|
||||
parentNode := parent.(*StepNode)
|
||||
|
||||
if parentNode.State == nil {
|
||||
return fmt.Errorf("parent %s of %s has nil state",
|
||||
parentNode.Step.Name, node.Step.Name)
|
||||
}
|
||||
|
||||
parentNodes[i] = parentNode
|
||||
}
|
||||
|
||||
merged := g.mergeNodes(parentNodes)
|
||||
currentState = &merged
|
||||
}
|
||||
|
||||
node.InputEnv = currentGraphEnv
|
||||
|
||||
// Convert this node's step to LLB
|
||||
stepState, err := g.convertNodeToLLB(node, currentState)
|
||||
stepState, err := g.convertNodeToLLB(node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -239,11 +268,8 @@ func (g *BuildGraph) processNode(node *StepNode) error {
|
||||
}
|
||||
|
||||
// convertNodeToLLB converts a step node to an LLB state
|
||||
func (g *BuildGraph) convertNodeToLLB(node *StepNode, baseState *llb.State) (*llb.State, error) {
|
||||
state := *baseState
|
||||
state = state.Dir("/app")
|
||||
|
||||
state, err := g.getNodeStartingState(state, node)
|
||||
func (g *BuildGraph) convertNodeToLLB(node *StepNode) (*llb.State, error) {
|
||||
state, err := g.getNodeStartingState(node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -259,28 +285,14 @@ func (g *BuildGraph) convertNodeToLLB(node *StepNode, baseState *llb.State) (*ll
|
||||
}
|
||||
}
|
||||
|
||||
if len(node.Step.Outputs) > 0 {
|
||||
newState := *baseState
|
||||
|
||||
// Copy the outputs directly to the new state
|
||||
for _, output := range node.Step.Outputs {
|
||||
newState = newState.File(llb.Copy(state, output, output, &llb.CopyInfo{
|
||||
CreateDestPath: true,
|
||||
AllowWildcard: true,
|
||||
AllowEmptyWildcard: true,
|
||||
FollowSymlinks: true,
|
||||
}), llb.WithCustomNamef("copying %s", output))
|
||||
}
|
||||
|
||||
state = newState
|
||||
}
|
||||
|
||||
return &state, nil
|
||||
}
|
||||
|
||||
// Adds the input environment to the base state of the node
|
||||
// This includes things like the environment variables and accumulated paths
|
||||
func (g *BuildGraph) getNodeStartingState(baseState llb.State, node *StepNode) (llb.State, error) {
|
||||
func (g *BuildGraph) getNodeStartingState(node *StepNode) (llb.State, error) {
|
||||
state := g.GetFullStateFromInputs(node.Step.Inputs).Dir("/app")
|
||||
|
||||
envVars := make(map[string]string)
|
||||
|
||||
// Collect all environment variables first
|
||||
@@ -293,13 +305,6 @@ func (g *BuildGraph) getNodeStartingState(baseState llb.State, node *StepNode) (
|
||||
node.OutputEnv.AddEnvVar(k, v)
|
||||
}
|
||||
|
||||
var state llb.State
|
||||
if node.Step.StartingImage != "" {
|
||||
state = llb.Image(node.Step.StartingImage, llb.Platform(*g.Platform)).Dir("/app")
|
||||
} else {
|
||||
state = baseState
|
||||
}
|
||||
|
||||
for _, k := range slices.Sorted(maps.Keys(envVars)) {
|
||||
state = state.AddEnv(k, envVars[k])
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package build_llb
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/moby/buildkit/client/llb"
|
||||
"github.com/railwayapp/railpack/core/plan"
|
||||
)
|
||||
@@ -33,7 +32,6 @@ func (c *BuildKitCacheStore) GetCache(key string, planCache *plan.Cache) BuildKi
|
||||
}
|
||||
|
||||
if cache, ok := c.CacheMap[cacheKey]; ok {
|
||||
log.Debugf("Cache %s already exists", cacheKey)
|
||||
return cache
|
||||
}
|
||||
|
||||
@@ -44,7 +42,6 @@ func (c *BuildKitCacheStore) GetCache(key string, planCache *plan.Cache) BuildKi
|
||||
planCache: planCache,
|
||||
cacheState: &cacheState,
|
||||
}
|
||||
log.Debugf("Creating new cache %s", cacheKey)
|
||||
|
||||
c.CacheMap[cacheKey] = cache
|
||||
|
||||
|
||||
+9
-59
@@ -27,8 +27,6 @@ const (
|
||||
func ConvertPlanToLLB(plan *p.BuildPlan, opts ConvertPlanOptions) (*llb.State, *Image, error) {
|
||||
platform := opts.BuildPlatform.ToPlatform()
|
||||
|
||||
state := getBaseState(plan, platform)
|
||||
|
||||
localState := llb.Local("context",
|
||||
llb.SharedKeyHint("local"),
|
||||
llb.SessionID(opts.SessionID),
|
||||
@@ -37,7 +35,7 @@ func ConvertPlanToLLB(plan *p.BuildPlan, opts ConvertPlanOptions) (*llb.State, *
|
||||
)
|
||||
|
||||
cacheStore := build_llb.NewBuildKitCacheStore(opts.CacheKey)
|
||||
graph, err := build_llb.NewBuildGraph(plan, &state, &localState, cacheStore, opts.SecretsHash, &platform)
|
||||
graph, err := build_llb.NewBuildGraph(plan, &localState, cacheStore, opts.SecretsHash, &platform)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -47,13 +45,11 @@ func ConvertPlanToLLB(plan *p.BuildPlan, opts ConvertPlanOptions) (*llb.State, *
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
state = *graphOutput.State
|
||||
state = getStartState(state, localState, plan, platform)
|
||||
|
||||
state := getStartState(*graphOutput.State)
|
||||
imageEnv := getImageEnv(graphOutput, plan)
|
||||
|
||||
startCommand := plan.Start.Command
|
||||
if plan.Start.Command == "" {
|
||||
startCommand := plan.Deploy.StartCmd
|
||||
if startCommand == "" {
|
||||
startCommand = "/bin/bash"
|
||||
}
|
||||
|
||||
@@ -79,58 +75,22 @@ func ConvertPlanToLLB(plan *p.BuildPlan, opts ConvertPlanOptions) (*llb.State, *
|
||||
return &state, &image, nil
|
||||
}
|
||||
|
||||
func getStartState(buildState llb.State, localState llb.State, plan *p.BuildPlan, platform specs.Platform) llb.State {
|
||||
// If there is no custom start image, we just copy over the outputs from the local state
|
||||
if plan.Start.BaseImage == "" {
|
||||
startState := buildState.Dir(WorkingDir)
|
||||
|
||||
// TODO: This is confusing and needs to change
|
||||
// If baseImage is provided, we are using `outputs` to copy files from the local state
|
||||
// If not provided, we are using `outputs` to copy files from the build state
|
||||
// Confusing and not good
|
||||
for _, path := range plan.Start.Outputs {
|
||||
startState = startState.File(llb.Copy(localState, path, path, &llb.CopyInfo{
|
||||
CreateDestPath: true,
|
||||
FollowSymlinks: true,
|
||||
CopyDirContentsOnly: true,
|
||||
}))
|
||||
}
|
||||
|
||||
return startState
|
||||
}
|
||||
|
||||
startState := llb.Image(plan.Start.BaseImage, llb.Platform(platform)).Dir(WorkingDir)
|
||||
|
||||
// This is all the user code + any modifications made by the providers
|
||||
mergedState := buildState.File(llb.Copy(localState, ".", ".", &llb.CopyInfo{
|
||||
CreateDestPath: true,
|
||||
FollowSymlinks: true,
|
||||
CopyDirContentsOnly: true,
|
||||
}))
|
||||
|
||||
// Copy over necessary files to the start image
|
||||
for _, path := range plan.Start.Outputs {
|
||||
startState = startState.File(llb.Copy(mergedState, path, path, &llb.CopyInfo{
|
||||
CreateDestPath: true,
|
||||
FollowSymlinks: true,
|
||||
CopyDirContentsOnly: true,
|
||||
}))
|
||||
}
|
||||
|
||||
func getStartState(buildState llb.State) llb.State {
|
||||
startState := buildState.Dir(WorkingDir)
|
||||
return startState
|
||||
}
|
||||
|
||||
func getImageEnv(graphOutput *build_llb.BuildGraphOutput, plan *p.BuildPlan) []string {
|
||||
paths := []string{}
|
||||
paths = append(paths, plan.Deploy.Paths...)
|
||||
paths = append(paths, graphOutput.GraphEnv.PathList...)
|
||||
paths = append(paths, plan.Start.Paths...)
|
||||
paths = append(paths, system.DefaultPathEnvUnix)
|
||||
slices.Sort(paths)
|
||||
pathString := strings.Join(paths, ":")
|
||||
|
||||
envMap := make(map[string]string, len(graphOutput.GraphEnv.EnvVars)+len(plan.Start.Variables)+1)
|
||||
envMap := make(map[string]string, len(graphOutput.GraphEnv.EnvVars)+len(plan.Deploy.Variables)+1)
|
||||
maps.Copy(envMap, graphOutput.GraphEnv.EnvVars)
|
||||
maps.Copy(envMap, plan.Start.Variables)
|
||||
maps.Copy(envMap, plan.Deploy.Variables)
|
||||
|
||||
envMap["PATH"] = pathString
|
||||
|
||||
@@ -142,13 +102,3 @@ func getImageEnv(graphOutput *build_llb.BuildGraphOutput, plan *p.BuildPlan) []s
|
||||
|
||||
return envVars
|
||||
}
|
||||
|
||||
func getBaseState(plan *p.BuildPlan, platform specs.Platform) llb.State {
|
||||
state := llb.Image(plan.BaseImage,
|
||||
llb.Platform(platform),
|
||||
)
|
||||
|
||||
state = state.AddEnv("DEBIAN_FRONTEND", "noninteractive").Dir(WorkingDir)
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
@@ -10,13 +9,39 @@
|
||||
"type": "locked"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "neofetch $HELLO",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:runtime"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
}
|
||||
],
|
||||
"startCommand": "neofetch $HELLO"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y neofetch'",
|
||||
"customName": "install apt packages: neofetch"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:runtime"
|
||||
},
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
@@ -26,13 +51,13 @@
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y neofetch'",
|
||||
"customName": "install apt packages: neofetch"
|
||||
},
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
{
|
||||
"customName": "create mise config",
|
||||
"name": "mise.toml",
|
||||
@@ -43,16 +68,12 @@
|
||||
"customName": "install mise packages: python"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -61,66 +82,6 @@
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"packages:apt:python-system-deps"
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y pkg-config'",
|
||||
"customName": "install apt packages: pkg-config"
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:python-system-deps",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y neofetch'",
|
||||
"customName": "install apt packages: neofetch"
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:config",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
@@ -128,9 +89,10 @@
|
||||
"customName": "neofetch"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"packages:apt:config"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
@@ -1,20 +1,37 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
"type": "locked"
|
||||
},
|
||||
"apt-lists": {
|
||||
"directory": "/var/lib/apt/lists",
|
||||
"type": "locked"
|
||||
},
|
||||
"go-build": {
|
||||
"directory": "/root/.cache/go-build",
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"baseImage": "alpine:latest",
|
||||
"cmd": "./out",
|
||||
"outputs": [
|
||||
"out"
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:runtime"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"variables": {
|
||||
"GIN_MODE": "release"
|
||||
}
|
||||
"startCommand": "./out"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
@@ -35,16 +52,12 @@
|
||||
"customName": "install mise packages: go"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -58,6 +71,9 @@
|
||||
"go-build"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/go/bin"
|
||||
},
|
||||
{
|
||||
"dest": "go.mod",
|
||||
"src": "go.mod"
|
||||
@@ -70,15 +86,19 @@
|
||||
"cmd": "go mod download"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"CGO_ENABLED": "0"
|
||||
"CGO_ENABLED": "0",
|
||||
"GOBIN": "/go/bin",
|
||||
"GOPATH": "/go"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -91,17 +111,36 @@
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "go build -o out ./cmd/server"
|
||||
"cmd": "go build -ldflags=\"-w -s\" -o out ./cmd/server"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y tzdata'",
|
||||
"customName": "install apt packages: tzdata"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:runtime"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,17 +1,37 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
"type": "locked"
|
||||
},
|
||||
"apt-lists": {
|
||||
"directory": "/var/lib/apt/lists",
|
||||
"type": "locked"
|
||||
},
|
||||
"go-build": {
|
||||
"directory": "/root/.cache/go-build",
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"baseImage": "alpine:latest",
|
||||
"cmd": "./out",
|
||||
"outputs": [
|
||||
"out"
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:runtime"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "./out"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
@@ -32,16 +52,12 @@
|
||||
"customName": "install mise packages: go"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -55,6 +71,9 @@
|
||||
"go-build"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/go/bin"
|
||||
},
|
||||
{
|
||||
"dest": "go.mod",
|
||||
"src": "go.mod"
|
||||
@@ -67,15 +86,19 @@
|
||||
"cmd": "go mod download"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"CGO_ENABLED": "0"
|
||||
"CGO_ENABLED": "0",
|
||||
"GOBIN": "/go/bin",
|
||||
"GOPATH": "/go"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -88,17 +111,36 @@
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "go build -o out"
|
||||
"cmd": "go build -ldflags=\"-w -s\" -o out"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y tzdata'",
|
||||
"customName": "install apt packages: tzdata"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:runtime"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"node-modules": {
|
||||
"directory": "/app/node_modules/.cache",
|
||||
@@ -10,11 +9,48 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "npm run start",
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise",
|
||||
"mise.toml"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "npm run start",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -47,17 +83,12 @@
|
||||
"customName": "install mise packages: node"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise",
|
||||
"/app/mise.toml"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -67,16 +98,27 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm install"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"name": "install",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -92,19 +134,18 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm install"
|
||||
"cmd": "npm prune --omit=dev"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -119,8 +160,10 @@
|
||||
"cmd": "npm run build"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"bun-install": {
|
||||
"directory": "/root/.bun/install/cache",
|
||||
@@ -10,11 +9,47 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "bun index.ts",
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "bun index.ts",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -40,19 +75,15 @@
|
||||
},
|
||||
{
|
||||
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
|
||||
"customName": "install mise packages: bun"
|
||||
"customName": "install mise packages: bun, go"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -62,16 +93,31 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"bun-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "bun.lockb",
|
||||
"src": "bun.lockb"
|
||||
},
|
||||
{
|
||||
"cmd": "bun install --frozen-lockfile"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"name": "install",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -87,23 +133,19 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "bun.lockb",
|
||||
"src": "bun.lockb"
|
||||
},
|
||||
{
|
||||
"cmd": "bun install --frozen-lockfile"
|
||||
"cmd": "sh -c 'rm -rf node_modules \u0026\u0026 bun install --production'",
|
||||
"customName": "rm -rf node_modules \u0026\u0026 bun install --production"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -118,8 +160,10 @@
|
||||
"cmd": "bun run build"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"node-modules": {
|
||||
"directory": "/app/node_modules/.cache",
|
||||
@@ -10,11 +9,48 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "pnpm run start",
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
".",
|
||||
"/root/.cache"
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "pnpm run start",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -43,16 +79,12 @@
|
||||
"customName": "install mise packages: node, pnpm"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -63,27 +95,13 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"pnpm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
@@ -93,20 +111,7 @@
|
||||
},
|
||||
{
|
||||
"cmd": "corepack prepare --activate"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup"
|
||||
],
|
||||
"name": "corepack",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"pnpm-install"
|
||||
],
|
||||
"commands": [
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
@@ -119,13 +124,39 @@
|
||||
"cmd": "pnpm install --frozen-lockfile --prod=false"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"corepack"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"pnpm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "pnpm prune --prod"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -140,8 +171,10 @@
|
||||
"cmd": "pnpm run build"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"next-": {
|
||||
"directory": "/app/.next/cache",
|
||||
@@ -14,11 +13,47 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "npm run start",
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "npm run start",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -47,16 +82,12 @@
|
||||
"customName": "install mise packages: node"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -66,16 +97,31 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "package-lock.json",
|
||||
"src": "package-lock.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm ci"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"name": "install",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -91,23 +137,18 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "package-lock.json",
|
||||
"src": "package-lock.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm ci"
|
||||
"cmd": "npm prune --omit=dev"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -123,8 +164,10 @@
|
||||
"cmd": "npm run build"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
+83
-40
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"node-modules": {
|
||||
"directory": "/app/node_modules/.cache",
|
||||
@@ -10,11 +9,47 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "node index.js",
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "node index.js",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -43,16 +78,12 @@
|
||||
"customName": "install mise packages: node"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -61,31 +92,14 @@
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
@@ -106,19 +120,48 @@
|
||||
"cmd": "npm ci"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "npm prune --omit=dev"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"node-modules"
|
||||
],
|
||||
"dependsOn": [
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"node-modules": {
|
||||
"directory": "/app/node_modules/.cache",
|
||||
@@ -10,11 +9,47 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "npm run start",
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "npm run start",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -43,16 +78,12 @@
|
||||
"customName": "install mise packages: node"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -62,16 +93,31 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "package-lock.json",
|
||||
"src": "package-lock.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm ci"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"name": "install",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -87,30 +133,27 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "package-lock.json",
|
||||
"src": "package-lock.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm ci"
|
||||
"cmd": "npm prune --omit=dev"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"node-modules"
|
||||
],
|
||||
"dependsOn": [
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
+103
-20
@@ -1,16 +1,55 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"node-modules": {
|
||||
"directory": "/app/node_modules/.cache",
|
||||
"type": "shared"
|
||||
},
|
||||
"pnpm-install": {
|
||||
"directory": "/root/.local/share/pnpm/store/v3",
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "node index.js",
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "node index.js",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -39,16 +78,12 @@
|
||||
"customName": "install mise packages: node, pnpm"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -58,16 +93,43 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"pnpm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "packages/pkg-a/package.json",
|
||||
"src": "packages/pkg-a/package.json"
|
||||
},
|
||||
{
|
||||
"dest": "packages/pkg-b/package.json",
|
||||
"src": "packages/pkg-b/package.json"
|
||||
},
|
||||
{
|
||||
"dest": "pnpm-workspace.yaml",
|
||||
"src": "pnpm-workspace.yaml"
|
||||
},
|
||||
{
|
||||
"dest": "pnpm-lock.yaml",
|
||||
"src": "pnpm-lock.yaml"
|
||||
},
|
||||
{
|
||||
"cmd": "pnpm install --frozen-lockfile --prod=false"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"name": "install",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
@@ -77,12 +139,33 @@
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"pnpm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "pnpm prune --prod"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"node-modules"
|
||||
],
|
||||
"dependsOn": [
|
||||
"setup"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"next-apps-docs": {
|
||||
"directory": "/app/apps/docs/.next/cache",
|
||||
@@ -18,9 +17,46 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"outputs": [
|
||||
"."
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
".",
|
||||
"/root/.cache"
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
@@ -50,16 +86,12 @@
|
||||
"customName": "install mise packages: node"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -70,27 +102,13 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [],
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
@@ -100,20 +118,7 @@
|
||||
},
|
||||
{
|
||||
"cmd": "corepack prepare --activate"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup"
|
||||
],
|
||||
"name": "corepack",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
@@ -150,13 +155,39 @@
|
||||
"cmd": "npm ci"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"corepack"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "npm prune --omit=dev"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "prune",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -173,8 +204,10 @@
|
||||
"cmd": "npm run build"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"install"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
|
||||
+188
-159
@@ -1,14 +1,5 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
"type": "locked"
|
||||
},
|
||||
"apt-lists": {
|
||||
"directory": "/var/lib/apt/lists",
|
||||
"type": "locked"
|
||||
},
|
||||
"composer": {
|
||||
"directory": "/opt/cache/composer",
|
||||
"type": "shared"
|
||||
@@ -22,164 +13,52 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "bash /start-nginx.sh",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install:composer"
|
||||
},
|
||||
{
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/app/node_modules"
|
||||
],
|
||||
"step": "prune:node"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "bash /start-nginx.sh",
|
||||
"variables": {
|
||||
"IS_LARAVEL": "true"
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"name": "packages:image",
|
||||
"secrets": [],
|
||||
"startingImage": "php:8.2.27-fpm"
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y git nginx unzip zip'",
|
||||
"customName": "install apt packages: git nginx unzip zip"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:image"
|
||||
],
|
||||
"name": "packages:apt:nginx",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"composer"
|
||||
],
|
||||
"commands": [
|
||||
"inputs": [
|
||||
{
|
||||
"dest": "/usr/bin/composer",
|
||||
"image": "composer:latest",
|
||||
"src": "/usr/bin/composer"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "composer install --ignore-platform-reqs"
|
||||
"image": "php:8.2.27-fpm"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:apt:nginx"
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"COMPOSER_CACHE_DIR": "/opt/cache/composer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
{
|
||||
"customName": "create mise config",
|
||||
"name": "mise.toml",
|
||||
"path": "/etc/mise/config.toml"
|
||||
},
|
||||
{
|
||||
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
|
||||
"customName": "install mise packages: node"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
"MISE_DATA_DIR": "/mise",
|
||||
"MISE_INSTALLS_DIR": "/mise/installs",
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup:node",
|
||||
"secrets": [],
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "package-lock.json",
|
||||
"src": "package-lock.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm ci"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup:node"
|
||||
],
|
||||
"name": "install:node",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"node-modules"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "npm run build"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"install:node"
|
||||
],
|
||||
"name": "build:node",
|
||||
"outputs": [
|
||||
"/app"
|
||||
],
|
||||
"name": "packages:image",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
@@ -211,16 +90,166 @@
|
||||
"path": "/start-nginx.sh"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:apt:nginx"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:image"
|
||||
}
|
||||
],
|
||||
"name": "nginx:setup",
|
||||
"name": "nginx",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"composer"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": "/usr/bin/composer",
|
||||
"image": "composer:latest",
|
||||
"src": "/usr/bin/composer"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "composer install --ignore-platform-reqs"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "nginx"
|
||||
}
|
||||
],
|
||||
"name": "install:composer",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"IS_LARAVEL": "true"
|
||||
"COMPOSER_CACHE_DIR": "/opt/cache/composer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
{
|
||||
"customName": "create mise config",
|
||||
"name": "mise.toml",
|
||||
"path": "/etc/mise/config.toml"
|
||||
},
|
||||
{
|
||||
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
|
||||
"customName": "install mise packages: node"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
"MISE_DATA_DIR": "/mise",
|
||||
"MISE_INSTALLS_DIR": "/mise/installs",
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/app/node_modules/.bin"
|
||||
},
|
||||
{
|
||||
"dest": "package.json",
|
||||
"src": "package.json"
|
||||
},
|
||||
{
|
||||
"dest": "package-lock.json",
|
||||
"src": "package-lock.json"
|
||||
},
|
||||
{
|
||||
"cmd": "npm ci"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install:node",
|
||||
"variables": {
|
||||
"CI": "true",
|
||||
"NODE_ENV": "production",
|
||||
"NPM_CONFIG_FUND": "false",
|
||||
"NPM_CONFIG_PRODUCTION": "false",
|
||||
"NPM_CONFIG_UPDATE_NOTIFIER": "false",
|
||||
"YARN_PRODUCTION": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"npm-install"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "npm prune --omit=dev"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install:node"
|
||||
}
|
||||
],
|
||||
"name": "prune:node",
|
||||
"variables": {
|
||||
"NPM_CONFIG_PRODUCTION": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"node-modules"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "npm run build"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install:composer"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
".",
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "install:node"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,76 +1,41 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
"type": "locked"
|
||||
},
|
||||
"apt-lists": {
|
||||
"directory": "/var/lib/apt/lists",
|
||||
"type": "locked"
|
||||
},
|
||||
"composer": {
|
||||
"directory": "/opt/cache/composer",
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "bash /start-nginx.sh",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "bash /start-nginx.sh"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"name": "packages:image",
|
||||
"secrets": [],
|
||||
"startingImage": "php:8.2.27-fpm"
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y git nginx unzip zip'",
|
||||
"customName": "install apt packages: git nginx unzip zip"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:image"
|
||||
],
|
||||
"name": "packages:apt:nginx",
|
||||
"secrets": []
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"composer"
|
||||
],
|
||||
"commands": [
|
||||
"inputs": [
|
||||
{
|
||||
"dest": "/usr/bin/composer",
|
||||
"image": "composer:latest",
|
||||
"src": "/usr/bin/composer"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "composer install --ignore-platform-reqs"
|
||||
"image": "php:8.2.27-fpm"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:apt:nginx"
|
||||
],
|
||||
"name": "install",
|
||||
"name": "packages:image",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"COMPOSER_CACHE_DIR": "/opt/cache/composer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"assets": {
|
||||
@@ -99,15 +64,64 @@
|
||||
"path": "/start-nginx.sh"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:apt:nginx"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:image"
|
||||
}
|
||||
],
|
||||
"name": "nginx:setup",
|
||||
"name": "nginx",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"composer"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"dest": "/usr/bin/composer",
|
||||
"image": "composer:latest",
|
||||
"src": "/usr/bin/composer"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "composer install --ignore-platform-reqs"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "nginx"
|
||||
}
|
||||
],
|
||||
"name": "install:composer",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"COMPOSER_CACHE_DIR": "/opt/cache/composer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install:composer"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"secrets": [
|
||||
"*"
|
||||
|
||||
@@ -1,43 +1,35 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
"type": "locked"
|
||||
},
|
||||
"apt-lists": {
|
||||
"directory": "/var/lib/apt/lists",
|
||||
"type": "locked"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "bash /start-nginx.sh",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "bash /start-nginx.sh"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"name": "packages:image",
|
||||
"secrets": [],
|
||||
"startingImage": "php:8.4.3-fpm"
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y git nginx unzip zip'",
|
||||
"customName": "install apt packages: git nginx unzip zip"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:image"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "php:8.4.3-fpm"
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:nginx",
|
||||
"secrets": []
|
||||
"name": "packages:image",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"assets": {
|
||||
@@ -66,15 +58,44 @@
|
||||
"path": "/start-nginx.sh"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:apt:nginx"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:image"
|
||||
}
|
||||
],
|
||||
"name": "nginx:setup",
|
||||
"name": "nginx",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "nginx"
|
||||
}
|
||||
],
|
||||
"name": "install:composer",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install:composer"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"secrets": [
|
||||
"*"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
@@ -10,18 +9,58 @@
|
||||
"type": "locked"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "python main.py",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:python-runtime-deps"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "python main.py",
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq-dev python3-dev'",
|
||||
"customName": "install apt packages: libpq-dev python3-dev"
|
||||
},
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
@@ -35,16 +74,12 @@
|
||||
"customName": "install mise packages: pipx, python"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -55,19 +90,34 @@
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "pipx install pdm"
|
||||
},
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "python --version"
|
||||
},
|
||||
{
|
||||
"cmd": "pdm install --check --prod --no-editable"
|
||||
},
|
||||
{
|
||||
"path": "/app/.venv/bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
"*"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PDM_CHECK_UPDATE": "false",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
@@ -77,39 +127,15 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
"inputs": [
|
||||
{
|
||||
"cmd": "pipx install pdm"
|
||||
},
|
||||
{
|
||||
"dest": "pyproject.toml",
|
||||
"src": "pyproject.toml"
|
||||
},
|
||||
{
|
||||
"dest": "pdm.lock",
|
||||
"src": "pdm.lock"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "pdm install --check --prod --no-editable"
|
||||
},
|
||||
{
|
||||
"path": "/app/.venv/bin"
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"packages:apt:python-system-deps"
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": [],
|
||||
"variables": {
|
||||
"PDM_CHECK_UPDATE": "false"
|
||||
}
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -118,12 +144,16 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y pkg-config'",
|
||||
"customName": "install apt packages: pkg-config"
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y '",
|
||||
"customName": "install apt packages: "
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:python-system-deps",
|
||||
"secrets": []
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:python-runtime-deps"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
@@ -14,18 +13,59 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "python main.py",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:python-runtime-deps"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/opt/python-packages",
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "python main.py",
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq-dev python3-dev'",
|
||||
"customName": "install apt packages: libpq-dev python3-dev"
|
||||
},
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
@@ -39,16 +79,12 @@
|
||||
"customName": "install mise packages: python"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -57,29 +93,6 @@
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"pip"
|
||||
@@ -90,16 +103,36 @@
|
||||
"src": "requirements.txt"
|
||||
},
|
||||
{
|
||||
"cmd": "pip install -r requirements.txt"
|
||||
"cmd": "pip install --target=/opt/python-packages -r requirements.txt"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"packages:apt:python-system-deps"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONPATH": "/opt/python-packages",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -108,12 +141,16 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y pkg-config'",
|
||||
"customName": "install apt packages: pkg-config"
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y '",
|
||||
"customName": "install apt packages: "
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:python-system-deps",
|
||||
"secrets": []
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:python-runtime-deps"
|
||||
}
|
||||
]
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
{
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
"type": "locked"
|
||||
},
|
||||
"apt-lists": {
|
||||
"directory": "/var/lib/apt/lists",
|
||||
"type": "locked"
|
||||
}
|
||||
},
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:python-runtime-deps"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "python main.py",
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq-dev python3-dev'",
|
||||
"customName": "install apt packages: libpq-dev python3-dev"
|
||||
},
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
{
|
||||
"customName": "create mise config",
|
||||
"name": "mise.toml",
|
||||
"path": "/etc/mise/config.toml"
|
||||
},
|
||||
{
|
||||
"cmd": "sh -c 'mise trust -a \u0026\u0026 mise install'",
|
||||
"customName": "install mise packages: pipx, python"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
"MISE_DATA_DIR": "/mise",
|
||||
"MISE_INSTALLS_DIR": "/mise/installs",
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "pipx install pipenv"
|
||||
},
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
},
|
||||
{
|
||||
"dest": "Pipfile",
|
||||
"src": "Pipfile"
|
||||
},
|
||||
{
|
||||
"dest": "Pipfile.lock",
|
||||
"src": "Pipfile.lock"
|
||||
},
|
||||
{
|
||||
"cmd": "pipenv install --deploy --ignore-pipfile"
|
||||
},
|
||||
{
|
||||
"path": "/app/.venv/bin"
|
||||
},
|
||||
{
|
||||
"dest": "Pipfile",
|
||||
"src": "Pipfile"
|
||||
},
|
||||
{
|
||||
"dest": "Pipfile.lock",
|
||||
"src": "Pipfile.lock"
|
||||
},
|
||||
{
|
||||
"cmd": "pipenv install --deploy --ignore-pipfile"
|
||||
},
|
||||
{
|
||||
"path": "/app/.venv/bin"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"variables": {
|
||||
"PIPENV_CHECK_UPDATE": "false",
|
||||
"PIPENV_IGNORE_VIRTUALENVS": "1",
|
||||
"PIPENV_VENV_IN_PROJECT": "1",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y '",
|
||||
"customName": "install apt packages: "
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:python-runtime-deps"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
@@ -10,18 +9,59 @@
|
||||
"type": "locked"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "python main.py",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:python-runtime-deps"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "python main.py",
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1",
|
||||
"VIRTUAL_ENV": "/app/.venv"
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq-dev python3-dev'",
|
||||
"customName": "install apt packages: libpq-dev python3-dev"
|
||||
},
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
@@ -35,16 +75,12 @@
|
||||
"customName": "install mise packages: pipx, python"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -53,36 +89,16 @@
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "pipx install poetry"
|
||||
},
|
||||
{
|
||||
"cmd": "poetry config virtualenvs.create false"
|
||||
"path": "/root/.local/bin"
|
||||
},
|
||||
{
|
||||
"cmd": "poetry config virtualenvs.in-project true"
|
||||
},
|
||||
{
|
||||
"dest": "pyproject.toml",
|
||||
@@ -93,16 +109,41 @@
|
||||
"src": "poetry.lock"
|
||||
},
|
||||
{
|
||||
"cmd": "poetry install --no-interaction --no-ansi --no-root"
|
||||
"cmd": "poetry install --no-interaction --no-ansi --only main --no-root"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"path": "/app/.venv/bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"packages:apt:python-system-deps"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -111,12 +152,16 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y pkg-config'",
|
||||
"customName": "install apt packages: pkg-config"
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y '",
|
||||
"customName": "install apt packages: "
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:python-system-deps",
|
||||
"secrets": []
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:python-runtime-deps"
|
||||
}
|
||||
]
|
||||
}
|
||||
+86
-49
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
@@ -14,18 +13,60 @@
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "python main.py",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:python-runtime-deps"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise",
|
||||
".python-version"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/opt/python-packages",
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "python main.py",
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq-dev python3-dev'",
|
||||
"customName": "install apt packages: libpq-dev python3-dev"
|
||||
},
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
@@ -43,17 +84,12 @@
|
||||
"customName": "install mise packages: python"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise",
|
||||
"/app/.python-version"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -62,29 +98,6 @@
|
||||
"MISE_SHIMS_DIR": "/mise/shims"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"pip"
|
||||
@@ -95,16 +108,36 @@
|
||||
"src": "requirements.txt"
|
||||
},
|
||||
{
|
||||
"cmd": "pip install -r requirements.txt"
|
||||
"cmd": "pip install --target=/opt/python-packages -r requirements.txt"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"packages:apt:python-system-deps"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": []
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONPATH": "/opt/python-packages",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
@@ -113,12 +146,16 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y ffmpeg gcc pkg-config poppler-utils'",
|
||||
"customName": "install apt packages: ffmpeg gcc pkg-config poppler-utils"
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y ffmpeg poppler-utils'",
|
||||
"customName": "install apt packages: ffmpeg poppler-utils"
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:python-system-deps",
|
||||
"secrets": []
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:python-runtime-deps"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
@@ -8,20 +7,65 @@
|
||||
"apt-lists": {
|
||||
"directory": "/var/lib/apt/lists",
|
||||
"type": "locked"
|
||||
},
|
||||
"uv": {
|
||||
"directory": "/opt/uv-cache",
|
||||
"type": "shared"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "gunicorn --bind 0.0.0.0:3333 main:app",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:python-runtime-deps"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise",
|
||||
".python-version"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "build"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "gunicorn --bind 0.0.0.0:3333 main:app",
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[mise.toml]"
|
||||
},
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libpq-dev python3-dev'",
|
||||
"customName": "install apt packages: libpq-dev python3-dev"
|
||||
},
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
@@ -39,17 +83,12 @@
|
||||
"customName": "install mise packages: pipx, python"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise",
|
||||
"/app/.python-version"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -59,33 +98,16 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
}
|
||||
"caches": [
|
||||
"uv"
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"PIP_CACHE_DIR": "/opt/pip-cache",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "pipx install uv"
|
||||
},
|
||||
{
|
||||
"path": "/root/.local/bin"
|
||||
},
|
||||
{
|
||||
"dest": "pyproject.toml",
|
||||
"src": "pyproject.toml"
|
||||
@@ -95,32 +117,52 @@
|
||||
"src": "uv.lock"
|
||||
},
|
||||
{
|
||||
"cmd": "uv sync --frozen --no-install-project --no-install-workspace --no-dev"
|
||||
"cmd": "uv sync --locked --no-dev --no-install-project"
|
||||
},
|
||||
{
|
||||
"dest": ".",
|
||||
"src": "."
|
||||
},
|
||||
{
|
||||
"cmd": "uv sync --frozen --no-dev"
|
||||
"cmd": "uv sync --locked --no-dev --no-editable"
|
||||
},
|
||||
{
|
||||
"path": "/app/.venv/bin"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise",
|
||||
"setup",
|
||||
"packages:apt:python-system-deps"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"secrets": [],
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
"variables": {
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PYTHONFAULTHANDLER": "1",
|
||||
"PYTHONHASHSEED": "random",
|
||||
"PYTHONUNBUFFERED": "1",
|
||||
"UV_CACHE_DIR": "/opt/uv-cache",
|
||||
"UV_COMPILE_BYTECODE": "1",
|
||||
"UV_LINK_MODE": "copy"
|
||||
"UV_LINK_MODE": "copy",
|
||||
"UV_PYTHON_DOWNLOADS": "never"
|
||||
}
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
@@ -128,12 +170,16 @@
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y pkg-config'",
|
||||
"customName": "install apt packages: pkg-config"
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y '",
|
||||
"customName": "install apt packages: "
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:python-system-deps",
|
||||
"secrets": []
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:python-runtime-deps"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,15 +1,42 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "defaultsToUsing"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "doesNotUseSecrets"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "usesSecrets"
|
||||
}
|
||||
],
|
||||
"startCommand": "./run.sh"
|
||||
},
|
||||
"secrets": [
|
||||
"MY_SECRET",
|
||||
"MY_OTHER_SECRET",
|
||||
"HELLO_WORLD"
|
||||
],
|
||||
"start": {
|
||||
"cmd": "./run.sh"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"secrets": [
|
||||
"*"
|
||||
@@ -26,13 +53,12 @@
|
||||
"customName": "./run.sh"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "defaultsToUsing",
|
||||
"outputs": [
|
||||
"/app"
|
||||
],
|
||||
"secrets": [
|
||||
"*"
|
||||
],
|
||||
@@ -51,14 +77,12 @@
|
||||
"customName": "./run.sh true"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "doesNotUseSecrets",
|
||||
"outputs": [
|
||||
"/app"
|
||||
],
|
||||
"secrets": []
|
||||
"name": "doesNotUseSecrets"
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
@@ -71,13 +95,12 @@
|
||||
"customName": "./run.sh"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "usesSecrets",
|
||||
"outputs": [
|
||||
"/app"
|
||||
],
|
||||
"secrets": [
|
||||
"MY_SECRET",
|
||||
"MY_OTHER_SECRET"
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"start": {
|
||||
"cmd": "caddy run --config Caddyfile --adapter caddyfile 2\u003e\u00261",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "setup"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "caddy run --config Caddyfile --adapter caddyfile 2\u003e\u00261"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
@@ -25,16 +48,12 @@
|
||||
"customName": "install mise packages: caddy"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -56,8 +75,10 @@
|
||||
"cmd": "caddy fmt --overwrite Caddyfile"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"start": {
|
||||
"cmd": "caddy run --config Caddyfile --adapter caddyfile 2\u003e\u00261",
|
||||
"outputs": [
|
||||
"."
|
||||
]
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
],
|
||||
"step": "packages:mise"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"step": "setup"
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"."
|
||||
],
|
||||
"local": true
|
||||
}
|
||||
],
|
||||
"startCommand": "caddy run --config Caddyfile --adapter caddyfile 2\u003e\u00261"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
@@ -25,16 +48,12 @@
|
||||
"customName": "install mise packages: caddy"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -56,8 +75,10 @@
|
||||
"cmd": "caddy fmt --overwrite Caddyfile"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:mise"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "setup",
|
||||
"secrets": [
|
||||
|
||||
+16
-23
@@ -6,30 +6,22 @@ import (
|
||||
"github.com/railwayapp/railpack/core/utils"
|
||||
)
|
||||
|
||||
type DeployConfig struct {
|
||||
AptPackages []string `json:"aptPackages,omitempty" jsonschema:"description=List of apt packages to include at runtime"`
|
||||
Inputs []plan.Input `json:"inputs,omitempty" jsonschema:"description=The inputs for the deploy step"`
|
||||
StartCmd string `json:"startCommand,omitempty" jsonschema:"description=The command to run in the container"`
|
||||
Variables map[string]string `json:"variables,omitempty" jsonschema:"description=The variables available to this step. The key is the name of the variable that is referenced in a variable command"`
|
||||
Paths []string `json:"paths,omitempty" jsonschema:"description=The paths to prepend to the $PATH environment variable"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
// The base image to use for the build
|
||||
BaseImage string `json:"baseImage,omitempty" jsonschema:"description=The base image to use for the build"`
|
||||
|
||||
// List of providers to use
|
||||
Providers *[]string `json:"providers,omitempty" jsonschema:"description=List of providers to use"`
|
||||
|
||||
// Map of step names to step definitions
|
||||
Steps map[string]*plan.Step `json:"steps,omitempty" jsonschema:"description=Map of step names to step definitions"`
|
||||
|
||||
// Start configuration
|
||||
Start plan.Start `json:"start,omitempty" jsonschema:"description=Start configuration"`
|
||||
|
||||
// Map of package name to package version
|
||||
Packages map[string]string `json:"packages,omitempty" jsonschema:"description=Map of package name to package version"`
|
||||
|
||||
// List of apt packages to install
|
||||
AptPackages []string `json:"aptPackages,omitempty" jsonschema:"description=List of apt packages to install"`
|
||||
|
||||
// Map of cache name to cache definitions. The cache key can be referenced in an exec command.
|
||||
Caches map[string]*plan.Cache `json:"caches,omitempty" jsonschema:"description=Map of cache name to cache definitions. The cache key can be referenced in an exec command"`
|
||||
|
||||
// Secrets that should be made available to commands that have useSecrets set to true
|
||||
Secrets []string `json:"secrets,omitempty" jsonschema:"description=Secrets that should be made available to commands that have useSecrets set to true"`
|
||||
Provider *string `json:"provider" jsonschema:"description=The provider to use"`
|
||||
BuildAptPackages []string `json:"buildAptPackages,omitempty" jsonschema:"description=List of apt packages to install during the build step"`
|
||||
Steps map[string]*plan.Step `json:"steps,omitempty" jsonschema:"description=Map of step names to step definitions"`
|
||||
Deploy *DeployConfig `json:"deploy,omitempty" jsonschema:"description=Deploy configuration"`
|
||||
Packages map[string]string `json:"packages,omitempty" jsonschema:"description=Map of package name to package version"`
|
||||
Caches map[string]*plan.Cache `json:"caches,omitempty" jsonschema:"description=Map of cache name to cache definitions. The cache key can be referenced in an exec command"`
|
||||
Secrets []string `json:"secrets,omitempty" jsonschema:"description=Secrets that should be made available to commands that have useSecrets set to true"`
|
||||
}
|
||||
|
||||
func EmptyConfig() *Config {
|
||||
@@ -37,6 +29,7 @@ func EmptyConfig() *Config {
|
||||
Steps: make(map[string]*plan.Step),
|
||||
Packages: make(map[string]string),
|
||||
Caches: make(map[string]*plan.Cache),
|
||||
Deploy: &DeployConfig{},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-28
@@ -13,8 +13,13 @@ func TestEmptyConfig(t *testing.T) {
|
||||
require.NotNil(t, config)
|
||||
require.Empty(t, config.Caches)
|
||||
require.Empty(t, config.Packages)
|
||||
require.Empty(t, config.AptPackages)
|
||||
require.Empty(t, config.BuildAptPackages)
|
||||
require.Empty(t, config.Steps)
|
||||
require.Nil(t, config.Provider)
|
||||
|
||||
require.NotNil(t, config.Deploy)
|
||||
require.Nil(t, config.Deploy.Inputs)
|
||||
require.Nil(t, config.Deploy.Paths)
|
||||
}
|
||||
|
||||
func TestMergeConfigSmall(t *testing.T) {
|
||||
@@ -37,7 +42,7 @@ func TestMergeConfigSmall(t *testing.T) {
|
||||
"caches": ["pip"]
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"deploy": {
|
||||
"variables": {
|
||||
"SHARED": "one",
|
||||
"HELLO": "world"
|
||||
@@ -58,7 +63,7 @@ func TestMergeConfigSmall(t *testing.T) {
|
||||
}
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"deploy": {
|
||||
"variables": {
|
||||
"SHARED": "two",
|
||||
"FOO": "bar"
|
||||
@@ -87,7 +92,7 @@ func TestMergeConfigSmall(t *testing.T) {
|
||||
"caches": ["pip"]
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"deploy": {
|
||||
"variables": {
|
||||
"HELLO": "world",
|
||||
"SHARED": "two",
|
||||
@@ -131,13 +136,11 @@ func TestMergeConfig(t *testing.T) {
|
||||
"steps": {
|
||||
"install": {
|
||||
"name": "install",
|
||||
"useSecrets": true,
|
||||
"outputs": ["node_modules/", "package-lock.json"],
|
||||
"secrets": ["*"],
|
||||
"assets": {
|
||||
"package.json": "content1",
|
||||
"requirements.txt": "content2"
|
||||
},
|
||||
"startingImage": "node:16",
|
||||
"commands": [
|
||||
{"type": "exec", "cmd": "npm install", "caches": ["npm"], "customName": "Install NPM deps"},
|
||||
{"type": "path", "path": "/usr/local/bin"},
|
||||
@@ -154,8 +157,8 @@ func TestMergeConfig(t *testing.T) {
|
||||
]
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"command": "python app.py"
|
||||
"deploy": {
|
||||
"startCommand": "python app.py"
|
||||
}
|
||||
}`
|
||||
|
||||
@@ -179,25 +182,23 @@ func TestMergeConfig(t *testing.T) {
|
||||
"steps": {
|
||||
"install": {
|
||||
"name": "install",
|
||||
"useSecrets": true,
|
||||
"outputs": ["dist/"],
|
||||
"secrets": ["*"],
|
||||
"assets": {
|
||||
"package.json": "content3"
|
||||
},
|
||||
"startingImage": "node:18"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"name": "build",
|
||||
"useSecrets": false,
|
||||
"secrets": [],
|
||||
"commands": [
|
||||
{"type": "exec", "cmd": "config 2 a"},
|
||||
{"type": "exec", "cmd": "config 2 b"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"baseImage": "node:18",
|
||||
"command": "node server.js",
|
||||
"deploy": {
|
||||
"aptPackages": ["curl"],
|
||||
"startCommand": "node server.js",
|
||||
"paths": ["/usr/local/bin", "/app/bin"]
|
||||
}
|
||||
}`
|
||||
@@ -226,13 +227,11 @@ func TestMergeConfig(t *testing.T) {
|
||||
"steps": {
|
||||
"install": {
|
||||
"name": "install",
|
||||
"useSecrets": true,
|
||||
"outputs": ["dist/"],
|
||||
"secrets": ["*"],
|
||||
"assets": {
|
||||
"package.json": "content3",
|
||||
"requirements.txt": "content2"
|
||||
},
|
||||
"startingImage": "node:18",
|
||||
"commands": [
|
||||
{"type": "exec", "cmd": "npm install", "caches": ["npm"], "customName": "Install NPM deps"},
|
||||
{"type": "path", "path": "/usr/local/bin"},
|
||||
@@ -243,16 +242,16 @@ func TestMergeConfig(t *testing.T) {
|
||||
},
|
||||
"build": {
|
||||
"name": "build",
|
||||
"useSecrets": false,
|
||||
"secrets": [],
|
||||
"commands": [
|
||||
{"type": "exec", "cmd": "config 2 a"},
|
||||
{"type": "exec", "cmd": "config 2 b"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"baseImage": "node:18",
|
||||
"command": "node server.js",
|
||||
"deploy": {
|
||||
"aptPackages": ["curl"],
|
||||
"startCommand": "node server.js",
|
||||
"paths": ["/usr/local/bin", "/app/bin"]
|
||||
}
|
||||
}`
|
||||
@@ -271,8 +270,8 @@ func TestMergeConfig(t *testing.T) {
|
||||
|
||||
func TestMergeConfigStart(t *testing.T) {
|
||||
config1JSON := `{
|
||||
"start": {
|
||||
"command": "python app.py"
|
||||
"deploy": {
|
||||
"startCommand": "python app.py"
|
||||
}
|
||||
}`
|
||||
|
||||
@@ -286,8 +285,8 @@ func TestMergeConfigStart(t *testing.T) {
|
||||
"packages": {
|
||||
"node": "23"
|
||||
},
|
||||
"start": {
|
||||
"command": "python app.py"
|
||||
"deploy": {
|
||||
"startCommand": "python app.py"
|
||||
},
|
||||
"steps": {},
|
||||
"caches": {}
|
||||
|
||||
+27
-39
@@ -33,7 +33,13 @@ type BuildResult struct {
|
||||
}
|
||||
|
||||
func GenerateBuildPlan(app *app.App, env *app.Environment, options *GenerateBuildPlanOptions) (*BuildResult, error) {
|
||||
ctx, err := generate.NewGenerateContext(app, env)
|
||||
// Get the full user config based on file config, env config, and options
|
||||
config, err := GetConfig(app, env, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, err := generate.NewGenerateContext(app, env, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -45,12 +51,6 @@ func GenerateBuildPlan(app *app.App, env *app.Environment, options *GenerateBuil
|
||||
}
|
||||
}
|
||||
|
||||
// Get the full user config based on file config, env config, and options
|
||||
config, err := GetConfig(app, env, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Figure out what providers to use
|
||||
providersToUse, detectedProviderNames := getProviders(ctx, config)
|
||||
providerNames := make([]string, len(providersToUse))
|
||||
@@ -82,11 +82,6 @@ func GenerateBuildPlan(app *app.App, env *app.Environment, options *GenerateBuil
|
||||
return nil, fmt.Errorf("failed to run procfile provider: %w", err)
|
||||
}
|
||||
|
||||
// Update the context with the config
|
||||
if err := ctx.ApplyConfig(config); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply config: %w", err)
|
||||
}
|
||||
|
||||
buildPlan, resolvedPackages, err := ctx.Generate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate build plan: %w", err)
|
||||
@@ -153,24 +148,16 @@ func GenerateConfigFromEnvironment(app *app.App, env *app.Environment) *config.C
|
||||
return config
|
||||
}
|
||||
|
||||
if installCmdVar, _ := env.GetConfigVariable("INSTALL_CMD"); installCmdVar != "" {
|
||||
installStep := config.GetOrCreateStep("install")
|
||||
installStep.Commands = []plan.Command{plan.NewExecShellCommand(installCmdVar, plan.ExecOptions{CustomName: installCmdVar})}
|
||||
installStep.DependsOn = append(installStep.DependsOn, "packages")
|
||||
}
|
||||
|
||||
if buildCmdVar, _ := env.GetConfigVariable("BUILD_CMD"); buildCmdVar != "" {
|
||||
buildStep := config.GetOrCreateStep("build")
|
||||
buildStep.Commands = []plan.Command{
|
||||
// We want to run the build command with all the files in the current directory
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecShellCommand(buildCmdVar, plan.ExecOptions{CustomName: buildCmdVar}),
|
||||
}
|
||||
buildStep.DependsOn = append(buildStep.DependsOn, "install")
|
||||
}
|
||||
|
||||
if startCmdVar, _ := env.GetConfigVariable("START_CMD"); startCmdVar != "" {
|
||||
config.Start.Command = startCmdVar
|
||||
config.Deploy.StartCmd = startCmdVar
|
||||
}
|
||||
|
||||
if envPackages, _ := env.GetConfigVariable("PACKAGES"); envPackages != "" {
|
||||
@@ -181,8 +168,12 @@ func GenerateConfigFromEnvironment(app *app.App, env *app.Environment) *config.C
|
||||
}
|
||||
}
|
||||
|
||||
if envAptPackages, _ := env.GetConfigVariable("APT_PACKAGES"); envAptPackages != "" {
|
||||
config.AptPackages = strings.Split(envAptPackages, " ")
|
||||
if envAptPackages, _ := env.GetConfigVariable("BUILD_APT_PACKAGES"); envAptPackages != "" {
|
||||
config.BuildAptPackages = strings.Split(envAptPackages, " ")
|
||||
}
|
||||
|
||||
if envAptPackages, _ := env.GetConfigVariable("DEPLOY_APT_PACKAGES"); envAptPackages != "" {
|
||||
config.Deploy.AptPackages = strings.Split(envAptPackages, " ")
|
||||
}
|
||||
|
||||
for name := range env.Variables {
|
||||
@@ -206,11 +197,10 @@ func GenerateConfigFromOptions(options *GenerateBuildPlanOptions) *config.Config
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecShellCommand(options.BuildCommand, plan.ExecOptions{CustomName: options.BuildCommand}),
|
||||
}
|
||||
buildStep.DependsOn = append(buildStep.DependsOn, "install")
|
||||
}
|
||||
|
||||
if options.StartCommand != "" {
|
||||
config.Start.Command = options.StartCommand
|
||||
config.Deploy.StartCmd = options.StartCommand
|
||||
}
|
||||
|
||||
return config
|
||||
@@ -234,7 +224,7 @@ func getProviders(ctx *generate.GenerateContext, config *config.Config) ([]provi
|
||||
detectedProviders = append(detectedProviders, provider.Name())
|
||||
|
||||
// If there are no providers manually specified in the config,
|
||||
if config.Providers == nil {
|
||||
if config.Provider == nil {
|
||||
if err := provider.Initialize(ctx); err != nil {
|
||||
log.Warnf("Failed to initialize provider `%s`: %s", provider.Name(), err.Error())
|
||||
continue
|
||||
@@ -246,20 +236,18 @@ func getProviders(ctx *generate.GenerateContext, config *config.Config) ([]provi
|
||||
}
|
||||
}
|
||||
|
||||
if config.Providers != nil {
|
||||
for _, providerName := range *config.Providers {
|
||||
provider := providers.GetProvider(providerName)
|
||||
if provider == nil {
|
||||
log.Warnf("Provider `%s` not found", providerName)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := provider.Initialize(ctx); err != nil {
|
||||
log.Warnf("Failed to initialize provider `%s`: %s", providerName, err.Error())
|
||||
continue
|
||||
}
|
||||
providersToUse = append(providersToUse, provider)
|
||||
if config.Provider != nil {
|
||||
provider := providers.GetProvider(*config.Provider)
|
||||
if provider == nil {
|
||||
log.Warnf("Provider `%s` not found", *config.Provider)
|
||||
return providersToUse, detectedProviders
|
||||
}
|
||||
|
||||
if err := provider.Initialize(ctx); err != nil {
|
||||
log.Warnf("Failed to initialize provider `%s`: %s", *config.Provider, err.Error())
|
||||
return providersToUse, detectedProviders
|
||||
}
|
||||
providersToUse = append(providersToUse, provider)
|
||||
}
|
||||
|
||||
return providersToUse, detectedProviders
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
[TestGenerateContext - 1]
|
||||
{
|
||||
"baseImage": "ghcr.io/railwayapp/railpack-runtime-base:latest",
|
||||
"caches": {
|
||||
"apt": {
|
||||
"directory": "/var/cache/apt",
|
||||
@@ -12,33 +11,30 @@
|
||||
"type": "locked"
|
||||
}
|
||||
},
|
||||
"secrets": [
|
||||
"RAILWAY_SECRET_1",
|
||||
"RAILWAY_SECRET_2"
|
||||
],
|
||||
"start": {
|
||||
"cmd": "npm run start",
|
||||
"deploy": {
|
||||
"inputs": [
|
||||
{
|
||||
"step": "build"
|
||||
}
|
||||
],
|
||||
"startCommand": "echo hello",
|
||||
"variables": {
|
||||
"HELLO": "world"
|
||||
}
|
||||
},
|
||||
"secrets": [
|
||||
"RAILWAY_SECRET_1",
|
||||
"RAILWAY_SECRET_2"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"assets": {
|
||||
"mise.toml": "[tools]\n [tools.go]\n version = \"1.23.5\"\n [tools.node]\n version = \"20.18.2\"\n [tools.python]\n version = \"3.13.1\"\n"
|
||||
},
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"path": "/mise/shims"
|
||||
},
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y curl'",
|
||||
"customName": "install apt packages: curl"
|
||||
},
|
||||
{
|
||||
"customName": "create mise config",
|
||||
"name": "mise.toml",
|
||||
@@ -49,16 +45,12 @@
|
||||
"customName": "install mise packages: go, node, python"
|
||||
}
|
||||
],
|
||||
"name": "packages:mise",
|
||||
"outputs": [
|
||||
"/mise/shims",
|
||||
"/mise/installs",
|
||||
"/usr/local/bin/mise",
|
||||
"/etc/mise/config.toml",
|
||||
"/root/.local/state/mise"
|
||||
"inputs": [
|
||||
{
|
||||
"image": "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
}
|
||||
],
|
||||
"secrets": [],
|
||||
"startingImage": "ghcr.io/railwayapp/railpack-builder-base:latest",
|
||||
"name": "packages:mise",
|
||||
"variables": {
|
||||
"MISE_CACHE_DIR": "/mise/cache",
|
||||
"MISE_CONFIG_DIR": "/mise",
|
||||
@@ -78,8 +70,12 @@
|
||||
"customName": "install apt packages: git neofetch"
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:test",
|
||||
"secrets": []
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:mise"
|
||||
}
|
||||
],
|
||||
"name": "packages:test"
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
@@ -87,16 +83,12 @@
|
||||
"cmd": "npm install"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"packages:apt:test"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "packages:test"
|
||||
}
|
||||
],
|
||||
"name": "install",
|
||||
"outputs": [
|
||||
"node_modules"
|
||||
],
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
"name": "install"
|
||||
},
|
||||
{
|
||||
"commands": [
|
||||
@@ -105,28 +97,15 @@
|
||||
"customName": "echo building"
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"install",
|
||||
"packages:apt:config"
|
||||
"inputs": [
|
||||
{
|
||||
"step": "install"
|
||||
}
|
||||
],
|
||||
"name": "build",
|
||||
"secrets": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"caches": [
|
||||
"apt",
|
||||
"apt-lists"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y curl'",
|
||||
"customName": "install apt packages: curl"
|
||||
}
|
||||
],
|
||||
"name": "packages:apt:config",
|
||||
"secrets": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,20 +4,19 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/railwayapp/railpack/core/plan"
|
||||
"github.com/railwayapp/railpack/core/utils"
|
||||
)
|
||||
|
||||
type AptStepBuilder struct {
|
||||
DisplayName string
|
||||
DependsOn []string
|
||||
Packages []string
|
||||
Inputs []plan.Input
|
||||
}
|
||||
|
||||
func (c *GenerateContext) NewAptStepBuilder(name string) *AptStepBuilder {
|
||||
step := &AptStepBuilder{
|
||||
DisplayName: c.GetStepName(fmt.Sprintf("packages:apt:%s", name)),
|
||||
DependsOn: []string{},
|
||||
DisplayName: c.GetStepName(fmt.Sprintf("packages:%s", name)),
|
||||
Packages: []string{},
|
||||
Inputs: []plan.Input{},
|
||||
}
|
||||
|
||||
c.Steps = append(c.Steps, step)
|
||||
@@ -25,6 +24,10 @@ func (c *GenerateContext) NewAptStepBuilder(name string) *AptStepBuilder {
|
||||
return step
|
||||
}
|
||||
|
||||
func (b *AptStepBuilder) AddInput(input plan.Input) {
|
||||
b.Inputs = append(b.Inputs, input)
|
||||
}
|
||||
|
||||
func (b *AptStepBuilder) AddAptPackage(pkg string) {
|
||||
b.Packages = append(b.Packages, pkg)
|
||||
}
|
||||
@@ -35,13 +38,13 @@ func (b *AptStepBuilder) Name() string {
|
||||
|
||||
func (b *AptStepBuilder) Build(options *BuildStepOptions) (*plan.Step, error) {
|
||||
step := plan.NewStep(b.DisplayName)
|
||||
step.DependsOn = utils.RemoveDuplicates(b.DependsOn)
|
||||
|
||||
step.AddCommands([]plan.Command{
|
||||
options.NewAptInstallCommand(b.Packages),
|
||||
})
|
||||
|
||||
step.Caches = options.Caches.GetAptCaches()
|
||||
step.Inputs = b.Inputs
|
||||
|
||||
// Does not use any secrets
|
||||
step.Secrets = []string{}
|
||||
|
||||
@@ -3,16 +3,15 @@ package generate
|
||||
import (
|
||||
"maps"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
a "github.com/railwayapp/railpack/core/app"
|
||||
"github.com/railwayapp/railpack/core/plan"
|
||||
"github.com/railwayapp/railpack/core/utils"
|
||||
)
|
||||
|
||||
type CommandStepBuilder struct {
|
||||
DisplayName string
|
||||
DependsOn []string
|
||||
Commands []plan.Command
|
||||
Outputs []string
|
||||
Inputs []plan.Input
|
||||
Assets map[string]string
|
||||
Variables map[string]string
|
||||
Caches []string
|
||||
@@ -24,7 +23,7 @@ type CommandStepBuilder struct {
|
||||
func (c *GenerateContext) NewCommandStep(name string) *CommandStepBuilder {
|
||||
step := &CommandStepBuilder{
|
||||
DisplayName: c.GetStepName(name),
|
||||
DependsOn: []string{MisePackageStepName},
|
||||
Inputs: []plan.Input{},
|
||||
Commands: []plan.Command{},
|
||||
Assets: map[string]string{},
|
||||
Variables: map[string]string{},
|
||||
@@ -34,13 +33,25 @@ func (c *GenerateContext) NewCommandStep(name string) *CommandStepBuilder {
|
||||
env: c.Env,
|
||||
}
|
||||
|
||||
// Remove any existing step with the same name
|
||||
for i, existingStep := range c.Steps {
|
||||
if existingStep.Name() == step.Name() {
|
||||
c.Steps = append(c.Steps[:i], c.Steps[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
c.Steps = append(c.Steps, step)
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (b *CommandStepBuilder) DependOn(name string) {
|
||||
b.DependsOn = append(b.DependsOn, name)
|
||||
func (b *CommandStepBuilder) AddInput(input plan.Input) {
|
||||
b.Inputs = append(b.Inputs, input)
|
||||
}
|
||||
|
||||
func (b *CommandStepBuilder) AddInputs(inputs []plan.Input) {
|
||||
b.Inputs = append(b.Inputs, inputs...)
|
||||
}
|
||||
|
||||
func (b *CommandStepBuilder) AddVariables(variables map[string]string) {
|
||||
@@ -48,6 +59,11 @@ func (b *CommandStepBuilder) AddVariables(variables map[string]string) {
|
||||
}
|
||||
|
||||
func (b *CommandStepBuilder) AddCache(name string) {
|
||||
if name == "" {
|
||||
log.Error("Cache name is empty")
|
||||
return
|
||||
}
|
||||
|
||||
b.Caches = append(b.Caches, name)
|
||||
}
|
||||
|
||||
@@ -98,8 +114,7 @@ func (b *CommandStepBuilder) Name() string {
|
||||
func (b *CommandStepBuilder) Build(options *BuildStepOptions) (*plan.Step, error) {
|
||||
step := plan.NewStep(b.DisplayName)
|
||||
|
||||
step.DependsOn = utils.RemoveDuplicates(b.DependsOn)
|
||||
step.Outputs = b.Outputs
|
||||
step.Inputs = b.Inputs
|
||||
step.Commands = b.Commands
|
||||
step.Assets = b.Assets
|
||||
step.Caches = b.Caches
|
||||
|
||||
+134
-138
@@ -16,10 +16,6 @@ import (
|
||||
"github.com/railwayapp/railpack/core/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultBaseImage = "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
)
|
||||
|
||||
type BuildStepOptions struct {
|
||||
ResolvedPackages map[string]*resolver.ResolvedPackage
|
||||
Caches *CacheContext
|
||||
@@ -31,49 +27,53 @@ type StepBuilder interface {
|
||||
}
|
||||
|
||||
type GenerateContext struct {
|
||||
App *a.App
|
||||
Env *a.Environment
|
||||
App *a.App
|
||||
Env *a.Environment
|
||||
Config *config.Config
|
||||
|
||||
BaseImage string
|
||||
Steps []StepBuilder
|
||||
Start StartContext
|
||||
Deploy *DeployBuilder
|
||||
|
||||
Caches *CacheContext
|
||||
Secrets []string
|
||||
|
||||
SubContexts []string
|
||||
|
||||
Metadata *Metadata
|
||||
|
||||
Resolver *resolver.Resolver
|
||||
|
||||
miseStepBuilder *MiseStepBuilder
|
||||
Metadata *Metadata
|
||||
Resolver *resolver.Resolver
|
||||
MiseStepBuilder *MiseStepBuilder
|
||||
}
|
||||
|
||||
func NewGenerateContext(app *a.App, env *a.Environment) (*GenerateContext, error) {
|
||||
func NewGenerateContext(app *a.App, env *a.Environment, config *config.Config) (*GenerateContext, error) {
|
||||
resolver, err := resolver.NewResolver(mise.InstallDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &GenerateContext{
|
||||
App: app,
|
||||
Env: env,
|
||||
BaseImage: DefaultBaseImage,
|
||||
Steps: make([]StepBuilder, 0),
|
||||
Start: *NewStartContext(),
|
||||
Caches: NewCacheContext(),
|
||||
Secrets: []string{},
|
||||
Metadata: NewMetadata(),
|
||||
Resolver: resolver,
|
||||
}, nil
|
||||
ctx := &GenerateContext{
|
||||
App: app,
|
||||
Env: env,
|
||||
Config: config,
|
||||
Steps: make([]StepBuilder, 0),
|
||||
Deploy: NewDeployBuilder(),
|
||||
Caches: NewCacheContext(),
|
||||
Secrets: []string{},
|
||||
Metadata: NewMetadata(),
|
||||
Resolver: resolver,
|
||||
}
|
||||
|
||||
// The default runtime image should include the runtime apt packages
|
||||
ctx.Deploy.Inputs = append(ctx.Deploy.Inputs, ctx.DefaultRuntimeInput())
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (c *GenerateContext) GetMiseStepBuilder() *MiseStepBuilder {
|
||||
if c.miseStepBuilder == nil {
|
||||
c.miseStepBuilder = c.newMiseStepBuilder()
|
||||
if c.MiseStepBuilder == nil {
|
||||
c.MiseStepBuilder = c.newMiseStepBuilder()
|
||||
}
|
||||
return c.miseStepBuilder
|
||||
return c.MiseStepBuilder
|
||||
}
|
||||
|
||||
func (c *GenerateContext) EnterSubContext(subContext string) *GenerateContext {
|
||||
@@ -109,16 +109,24 @@ func (c *GenerateContext) ResolvePackages() (map[string]*resolver.ResolvedPackag
|
||||
|
||||
// Generate a build plan from the context
|
||||
func (c *GenerateContext) Generate() (*plan.BuildPlan, map[string]*resolver.ResolvedPackage, error) {
|
||||
// Add all packages from the config to the mise step
|
||||
miseStep := c.GetMiseStepBuilder()
|
||||
for _, pkg := range slices.Sorted(maps.Keys(c.Config.Packages)) {
|
||||
version := c.Config.Packages[pkg]
|
||||
pkgRef := miseStep.Default(pkg, version)
|
||||
miseStep.Version(pkgRef, version, "custom config")
|
||||
}
|
||||
|
||||
c.applyConfig()
|
||||
|
||||
// Resolve all package versions into a fully qualified and valid version
|
||||
resolvedPackages, err := c.ResolvePackages()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to resolve packages: %w", err)
|
||||
}
|
||||
|
||||
// Generate the plan based on the context and resolved packages
|
||||
|
||||
// Create the actual build plan
|
||||
buildPlan := plan.NewBuildPlan()
|
||||
buildPlan.BaseImage = c.BaseImage
|
||||
|
||||
buildStepOptions := &BuildStepOptions{
|
||||
ResolvedPackages: resolvedPackages,
|
||||
@@ -136,122 +144,28 @@ func (c *GenerateContext) Generate() (*plan.BuildPlan, map[string]*resolver.Reso
|
||||
}
|
||||
|
||||
buildPlan.Caches = c.Caches.Caches
|
||||
|
||||
buildPlan.Secrets = utils.RemoveDuplicates(c.Secrets)
|
||||
|
||||
buildPlan.Start.BaseImage = c.Start.BaseImage
|
||||
buildPlan.Start.Command = c.Start.Command
|
||||
buildPlan.Start.Outputs = utils.RemoveDuplicates(c.Start.outputs)
|
||||
buildPlan.Start.Paths = utils.RemoveDuplicates(c.Start.paths)
|
||||
buildPlan.Start.Variables = c.Start.variables
|
||||
buildPlan.Deploy = c.Deploy.Build()
|
||||
|
||||
return buildPlan, resolvedPackages, nil
|
||||
}
|
||||
|
||||
func (c *GenerateContext) ApplyConfig(config *config.Config) error {
|
||||
// Mise package config
|
||||
miseStep := c.GetMiseStepBuilder()
|
||||
for _, pkg := range slices.Sorted(maps.Keys(config.Packages)) {
|
||||
version := config.Packages[pkg]
|
||||
pkgRef := miseStep.Default(pkg, version)
|
||||
miseStep.Version(pkgRef, version, "custom config")
|
||||
func (c *GenerateContext) DefaultRuntimeInput() plan.Input {
|
||||
return c.DefaultRuntimeInputWithPackages([]string{})
|
||||
}
|
||||
|
||||
func (c *GenerateContext) DefaultRuntimeInputWithPackages(additionalAptPackages []string) plan.Input {
|
||||
aptPackages := append(c.Config.Deploy.AptPackages, additionalAptPackages...)
|
||||
|
||||
if len(aptPackages) == 0 {
|
||||
return plan.NewImageInput(plan.RAILPACK_RUNTIME_IMAGE)
|
||||
}
|
||||
|
||||
// Apt package config
|
||||
aptStepName := ""
|
||||
if len(config.AptPackages) > 0 {
|
||||
aptStep := c.NewAptStepBuilder("config")
|
||||
aptStepName = aptStep.Name()
|
||||
aptStep.Packages = config.AptPackages
|
||||
runtimeAptStep := c.NewAptStepBuilder("runtime")
|
||||
runtimeAptStep.Packages = aptPackages
|
||||
runtimeAptStep.AddInput(plan.NewImageInput(plan.RAILPACK_RUNTIME_IMAGE))
|
||||
|
||||
// We install the apt packages again in the mise step since they may be required for install mise packages
|
||||
miseStep.SupportingAptPackages = append(miseStep.SupportingAptPackages, config.AptPackages...)
|
||||
}
|
||||
|
||||
// Step config
|
||||
for _, name := range slices.Sorted(maps.Keys(config.Steps)) {
|
||||
configStep := config.Steps[name]
|
||||
|
||||
var commandStepBuilder *CommandStepBuilder
|
||||
|
||||
// We need to use the key as the step name and not `configStep.Name`
|
||||
if existingStep := c.GetStepByName(name); existingStep != nil {
|
||||
if csb, ok := (*existingStep).(*CommandStepBuilder); ok {
|
||||
commandStepBuilder = csb
|
||||
} else {
|
||||
log.Warnf("Step `%s` exists, but it is not a command step. Skipping...", name)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
commandStepBuilder = c.NewCommandStep(name)
|
||||
}
|
||||
|
||||
// Overwrite the step with values from the config if they exist
|
||||
|
||||
if len(configStep.DependsOn) > 0 {
|
||||
commandStepBuilder.DependsOn = configStep.DependsOn
|
||||
}
|
||||
|
||||
if aptStepName != "" {
|
||||
commandStepBuilder.DependsOn = append(commandStepBuilder.DependsOn, aptStepName)
|
||||
}
|
||||
|
||||
if configStep.Commands != nil {
|
||||
commandStepBuilder.Commands = configStep.Commands
|
||||
}
|
||||
|
||||
if configStep.Outputs != nil {
|
||||
commandStepBuilder.Outputs = configStep.Outputs
|
||||
}
|
||||
for k, v := range configStep.Assets {
|
||||
commandStepBuilder.Assets[k] = v
|
||||
}
|
||||
|
||||
if configStep.Secrets != nil {
|
||||
commandStepBuilder.Secrets = configStep.Secrets
|
||||
}
|
||||
|
||||
// if configStep.UseSecrets != nil {
|
||||
// commandStepBuilder.UseSecrets = *configStep.UseSecrets
|
||||
// }
|
||||
|
||||
if len(configStep.Caches) > 0 {
|
||||
commandStepBuilder.Caches = configStep.Caches
|
||||
}
|
||||
|
||||
if configStep.Variables != nil {
|
||||
commandStepBuilder.AddEnvVars(configStep.Variables)
|
||||
}
|
||||
}
|
||||
|
||||
// Cache config
|
||||
for name, cache := range config.Caches {
|
||||
c.Caches.SetCache(name, cache)
|
||||
}
|
||||
|
||||
// Secret config
|
||||
c.Secrets = append(c.Secrets, config.Secrets...)
|
||||
|
||||
// Start config
|
||||
if config.Start.BaseImage != "" {
|
||||
c.Start.BaseImage = config.Start.BaseImage
|
||||
}
|
||||
|
||||
if config.Start.Command != "" {
|
||||
c.Start.Command = config.Start.Command
|
||||
}
|
||||
|
||||
if config.Start.Variables != nil {
|
||||
c.Start.AddEnvVars(config.Start.Variables)
|
||||
}
|
||||
|
||||
c.Start.AddPaths(config.Start.Paths)
|
||||
|
||||
if len(config.Start.Outputs) > 0 {
|
||||
c.Start.outputs = config.Start.Outputs
|
||||
}
|
||||
|
||||
return nil
|
||||
return plan.NewStepInput(runtimeAptStep.Name())
|
||||
}
|
||||
|
||||
func (o *BuildStepOptions) NewAptInstallCommand(pkgs []string) plan.Command {
|
||||
@@ -262,3 +176,85 @@ func (o *BuildStepOptions) NewAptInstallCommand(pkgs []string) plan.Command {
|
||||
CustomName: "install apt packages: " + strings.Join(pkgs, " "),
|
||||
})
|
||||
}
|
||||
|
||||
func (c *GenerateContext) applyConfig() {
|
||||
miseStep := c.GetMiseStepBuilder()
|
||||
|
||||
// Apply the cache config to the context
|
||||
maps.Copy(c.Caches.Caches, c.Config.Caches)
|
||||
|
||||
// Apply step config to the context
|
||||
for _, name := range slices.Sorted(maps.Keys(c.Config.Steps)) {
|
||||
configStep := c.Config.Steps[name]
|
||||
|
||||
var commandStepBuilder *CommandStepBuilder
|
||||
|
||||
if existingStep := c.GetStepByName(name); existingStep != nil {
|
||||
if csb, ok := (*existingStep).(*CommandStepBuilder); ok {
|
||||
commandStepBuilder = csb
|
||||
} else {
|
||||
log.Warnf("Step `%s` exists, but it is not a command step. Skipping...", name)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// If no build step found, create a new one
|
||||
// Run the build in the builder context and copy the /app contents to the final image
|
||||
commandStepBuilder = c.NewCommandStep(name)
|
||||
commandStepBuilder.AddInput(plan.NewStepInput(miseStep.Name()))
|
||||
c.Deploy.Inputs = append(c.Deploy.Inputs, plan.NewStepInput(commandStepBuilder.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}))
|
||||
}
|
||||
|
||||
if configStep.Commands != nil {
|
||||
commandStepBuilder.Commands = configStep.Commands
|
||||
}
|
||||
|
||||
if configStep.Inputs != nil {
|
||||
commandStepBuilder.Inputs = configStep.Inputs
|
||||
}
|
||||
|
||||
for k, v := range configStep.Assets {
|
||||
commandStepBuilder.Assets[k] = v
|
||||
}
|
||||
|
||||
if configStep.Secrets != nil {
|
||||
commandStepBuilder.Secrets = configStep.Secrets
|
||||
}
|
||||
|
||||
if len(configStep.Caches) > 0 {
|
||||
commandStepBuilder.Caches = configStep.Caches
|
||||
}
|
||||
|
||||
if configStep.Variables != nil {
|
||||
commandStepBuilder.AddEnvVars(configStep.Variables)
|
||||
}
|
||||
|
||||
// Secret config
|
||||
if configStep.Secrets != nil {
|
||||
commandStepBuilder.Secrets = configStep.Secrets
|
||||
}
|
||||
}
|
||||
|
||||
if c.Config.Secrets != nil {
|
||||
c.Secrets = c.Config.Secrets
|
||||
}
|
||||
|
||||
// Update deploy from config
|
||||
if c.Config.Deploy != nil {
|
||||
if c.Config.Deploy.StartCmd != "" {
|
||||
c.Deploy.StartCmd = c.Config.Deploy.StartCmd
|
||||
}
|
||||
|
||||
if c.Config.Deploy.Inputs != nil {
|
||||
c.Deploy.Inputs = c.Config.Deploy.Inputs
|
||||
}
|
||||
|
||||
if c.Config.Deploy.Paths != nil {
|
||||
c.Deploy.Paths = c.Config.Deploy.Paths
|
||||
}
|
||||
|
||||
maps.Copy(c.Deploy.Variables, c.Config.Deploy.Variables)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,20 +21,23 @@ func (p *TestProvider) Plan(ctx *GenerateContext) error {
|
||||
|
||||
// apt
|
||||
aptStep := ctx.NewAptStepBuilder("test")
|
||||
aptStep.AddInput(plan.NewStepInput(mise.Name()))
|
||||
aptStep.AddAptPackage("git")
|
||||
aptStep.AddAptPackage("neofetch")
|
||||
|
||||
// commands
|
||||
installStep := ctx.NewCommandStep("install")
|
||||
installStep.AddCommand(plan.NewExecCommand("npm install", plan.ExecOptions{}))
|
||||
installStep.Outputs = []string{"node_modules"}
|
||||
installStep.DependsOn = []string{aptStep.Name()}
|
||||
installStep.AddInput(plan.NewStepInput(aptStep.Name()))
|
||||
installStep.Secrets = []string{}
|
||||
|
||||
buildStep := ctx.NewCommandStep("build")
|
||||
buildStep.AddCommand(plan.NewExecCommand("npm run build", plan.ExecOptions{}))
|
||||
buildStep.DependsOn = []string{installStep.Name()}
|
||||
buildStep.AddInput(plan.NewStepInput(installStep.Name()))
|
||||
|
||||
ctx.Start.Command = "npm run start"
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(buildStep.Name()),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -46,8 +49,9 @@ func CreateTestContext(t *testing.T, path string) *GenerateContext {
|
||||
require.NoError(t, err)
|
||||
|
||||
env := app.NewEnvironment(nil)
|
||||
config := config.EmptyConfig()
|
||||
|
||||
ctx, err := NewGenerateContext(userApp, env)
|
||||
ctx, err := NewGenerateContext(userApp, env, config)
|
||||
require.NoError(t, err)
|
||||
|
||||
return ctx
|
||||
@@ -72,39 +76,23 @@ func TestGenerateContext(t *testing.T) {
|
||||
}
|
||||
},
|
||||
"secrets": ["RAILWAY_SECRET_1", "RAILWAY_SECRET_2"],
|
||||
"start": {
|
||||
"deploy": {
|
||||
"startCommand": "echo hello",
|
||||
"variables": {
|
||||
"HELLO": "world"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
var cfg config.Config
|
||||
require.NoError(t, json.Unmarshal([]byte(configJSON), &cfg))
|
||||
var config config.Config
|
||||
require.NoError(t, json.Unmarshal([]byte(configJSON), &config))
|
||||
|
||||
// Apply the config to the context
|
||||
require.NoError(t, ctx.ApplyConfig(&cfg))
|
||||
|
||||
// Resolve packages
|
||||
resolvedPkgs, err := ctx.ResolvePackages()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Generate a plan
|
||||
buildOpts := &BuildStepOptions{
|
||||
ResolvedPackages: resolvedPkgs,
|
||||
Caches: ctx.Caches,
|
||||
}
|
||||
|
||||
// Build and verify each step
|
||||
for _, builder := range ctx.Steps {
|
||||
_, err := builder.Build(buildOpts)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
ctx.Config = &config
|
||||
|
||||
buildPlan, _, err := ctx.Generate()
|
||||
require.NoError(t, err)
|
||||
|
||||
buildPlanJSON, err := json.Marshal(buildPlan)
|
||||
buildPlanJSON, err := json.MarshalIndent(buildPlan, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
var actualPlan map[string]interface{}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package generate
|
||||
|
||||
import "github.com/railwayapp/railpack/core/plan"
|
||||
|
||||
type DeployBuilder struct {
|
||||
Inputs []plan.Input
|
||||
StartCmd string
|
||||
Variables map[string]string
|
||||
Paths []string
|
||||
AptPackages []string
|
||||
}
|
||||
|
||||
func NewDeployBuilder() *DeployBuilder {
|
||||
return &DeployBuilder{
|
||||
Inputs: []plan.Input{},
|
||||
StartCmd: "",
|
||||
Variables: map[string]string{},
|
||||
Paths: []string{},
|
||||
AptPackages: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
func (b *DeployBuilder) Build() plan.Deploy {
|
||||
return plan.Deploy{
|
||||
Inputs: b.Inputs,
|
||||
StartCmd: b.StartCmd,
|
||||
Variables: b.Variables,
|
||||
Paths: b.Paths,
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@ type ImageStepBuilder struct {
|
||||
DisplayName string
|
||||
Resolver *resolver.Resolver
|
||||
Packages []*resolver.PackageRef
|
||||
Outputs []string
|
||||
ResolveStepImage func(options *BuildStepOptions) string
|
||||
AptPackages []string
|
||||
}
|
||||
|
||||
func (c *GenerateContext) NewImageStep(name string, resolveStepImage func(options *BuildStepOptions) string) *ImageStepBuilder {
|
||||
@@ -46,11 +46,18 @@ func (b *ImageStepBuilder) Name() string {
|
||||
}
|
||||
|
||||
func (b *ImageStepBuilder) Build(options *BuildStepOptions) (*plan.Step, error) {
|
||||
step := plan.NewStep(b.DisplayName)
|
||||
image := b.ResolveStepImage(options)
|
||||
|
||||
step.StartingImage = b.ResolveStepImage(options)
|
||||
step.Outputs = b.Outputs
|
||||
step.Secrets = []string{}
|
||||
step := plan.NewStep(b.DisplayName)
|
||||
step.Inputs = []plan.Input{
|
||||
plan.NewImageInput(image),
|
||||
}
|
||||
|
||||
if len(b.AptPackages) > 0 {
|
||||
step.Commands = []plan.Command{
|
||||
options.NewAptInstallCommand(b.AptPackages),
|
||||
}
|
||||
}
|
||||
|
||||
return step, nil
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
|
||||
const (
|
||||
MisePackageStepName = "packages:mise"
|
||||
BuilderBaseImage = "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
)
|
||||
|
||||
type MiseStepBuilder struct {
|
||||
@@ -24,20 +23,22 @@ type MiseStepBuilder struct {
|
||||
MisePackages []*resolver.PackageRef
|
||||
SupportingMiseFiles []string
|
||||
Assets map[string]string
|
||||
Outputs []string
|
||||
Inputs []plan.Input
|
||||
Variables map[string]string
|
||||
app *a.App
|
||||
env *a.Environment
|
||||
}
|
||||
|
||||
func (c *GenerateContext) newMiseStepBuilder() *MiseStepBuilder {
|
||||
supportingAptPackages := c.Config.BuildAptPackages
|
||||
|
||||
step := &MiseStepBuilder{
|
||||
DisplayName: MisePackageStepName,
|
||||
Resolver: c.Resolver,
|
||||
MisePackages: []*resolver.PackageRef{},
|
||||
SupportingAptPackages: []string{},
|
||||
SupportingAptPackages: append(supportingAptPackages, c.Config.BuildAptPackages...),
|
||||
Assets: map[string]string{},
|
||||
Outputs: []string{"/mise/shims", "/mise/installs", "/usr/local/bin/mise", "/etc/mise/config.toml", "/root/.local/state/mise"},
|
||||
Inputs: []plan.Input{},
|
||||
Variables: map[string]string{},
|
||||
app: c.App,
|
||||
env: c.Env,
|
||||
@@ -52,6 +53,10 @@ func (b *MiseStepBuilder) AddSupportingAptPackage(name string) {
|
||||
b.SupportingAptPackages = append(b.SupportingAptPackages, name)
|
||||
}
|
||||
|
||||
func (b *MiseStepBuilder) AddInput(input plan.Input) {
|
||||
b.Inputs = append(b.Inputs, input)
|
||||
}
|
||||
|
||||
func (b *MiseStepBuilder) Default(name string, defaultVersion string) resolver.PackageRef {
|
||||
for _, pkg := range b.MisePackages {
|
||||
if pkg.Name == name {
|
||||
@@ -72,15 +77,32 @@ func (b *MiseStepBuilder) Name() string {
|
||||
return b.DisplayName
|
||||
}
|
||||
|
||||
func (b *MiseStepBuilder) GetOutputPaths() []string {
|
||||
supportingMiseConfigFiles := b.GetSupportingMiseConfigFiles(b.app.Source)
|
||||
files := []string{"/mise/shims", "/mise/installs", "/usr/local/bin/mise", "/etc/mise/config.toml", "/root/.local/state/mise"}
|
||||
files = append(files, supportingMiseConfigFiles...)
|
||||
return files
|
||||
}
|
||||
|
||||
func (b *MiseStepBuilder) Build(options *BuildStepOptions) (*plan.Step, error) {
|
||||
step := plan.NewStep(b.DisplayName)
|
||||
|
||||
step.Inputs = []plan.Input{
|
||||
plan.NewImageInput(plan.RAILPACK_BUILDER_IMAGE),
|
||||
}
|
||||
|
||||
// Setup apt commands
|
||||
if len(b.SupportingAptPackages) > 0 {
|
||||
step.AddCommands([]plan.Command{
|
||||
options.NewAptInstallCommand(b.SupportingAptPackages),
|
||||
})
|
||||
step.Caches = options.Caches.GetAptCaches()
|
||||
}
|
||||
|
||||
if len(b.MisePackages) == 0 {
|
||||
return step, nil
|
||||
}
|
||||
|
||||
step.StartingImage = BuilderBaseImage
|
||||
|
||||
// Setup mise
|
||||
step.AddCommands([]plan.Command{
|
||||
plan.NewPathCommand("/mise/shims"),
|
||||
@@ -104,54 +126,40 @@ func (b *MiseStepBuilder) Build(options *BuildStepOptions) (*plan.Step, error) {
|
||||
step.AddCommands([]plan.Command{
|
||||
plan.NewCopyCommand(file, "/app/"+file),
|
||||
})
|
||||
|
||||
// We want to make sure the file is copied into the next step
|
||||
b.Outputs = append(b.Outputs, "/app/"+file)
|
||||
}
|
||||
|
||||
// Setup apt commands
|
||||
if len(b.SupportingAptPackages) > 0 {
|
||||
step.AddCommands([]plan.Command{
|
||||
options.NewAptInstallCommand(b.SupportingAptPackages),
|
||||
})
|
||||
step.Caches = options.Caches.GetAptCaches()
|
||||
}
|
||||
|
||||
// Setup mise commands
|
||||
if len(b.MisePackages) > 0 {
|
||||
packagesToInstall := make(map[string]string)
|
||||
for _, pkg := range b.MisePackages {
|
||||
resolved, ok := options.ResolvedPackages[pkg.Name]
|
||||
if ok && resolved.ResolvedVersion != nil {
|
||||
packagesToInstall[pkg.Name] = *resolved.ResolvedVersion
|
||||
}
|
||||
packagesToInstall := make(map[string]string)
|
||||
for _, pkg := range b.MisePackages {
|
||||
resolved, ok := options.ResolvedPackages[pkg.Name]
|
||||
if ok && resolved.ResolvedVersion != nil {
|
||||
packagesToInstall[pkg.Name] = *resolved.ResolvedVersion
|
||||
}
|
||||
|
||||
miseToml, err := mise.GenerateMiseToml(packagesToInstall)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate mise.toml: %w", err)
|
||||
}
|
||||
|
||||
b.Assets["mise.toml"] = miseToml
|
||||
|
||||
pkgNames := make([]string, 0, len(packagesToInstall))
|
||||
for k := range packagesToInstall {
|
||||
pkgNames = append(pkgNames, k)
|
||||
}
|
||||
sort.Strings(pkgNames)
|
||||
|
||||
step.AddCommands([]plan.Command{
|
||||
plan.NewFileCommand("/etc/mise/config.toml", "mise.toml", plan.FileOptions{
|
||||
CustomName: "create mise config",
|
||||
}),
|
||||
plan.NewExecCommand("sh -c 'mise trust -a && mise install'", plan.ExecOptions{
|
||||
CustomName: "install mise packages: " + strings.Join(pkgNames, ", "),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
miseToml, err := mise.GenerateMiseToml(packagesToInstall)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate mise.toml: %w", err)
|
||||
}
|
||||
|
||||
b.Assets["mise.toml"] = miseToml
|
||||
|
||||
pkgNames := make([]string, 0, len(packagesToInstall))
|
||||
for k := range packagesToInstall {
|
||||
pkgNames = append(pkgNames, k)
|
||||
}
|
||||
sort.Strings(pkgNames)
|
||||
|
||||
step.AddCommands([]plan.Command{
|
||||
plan.NewFileCommand("/etc/mise/config.toml", "mise.toml", plan.FileOptions{
|
||||
CustomName: "create mise config",
|
||||
}),
|
||||
plan.NewExecCommand("sh -c 'mise trust -a && mise install'", plan.ExecOptions{
|
||||
CustomName: "install mise packages: " + strings.Join(pkgNames, ", "),
|
||||
}),
|
||||
})
|
||||
|
||||
step.Assets = b.Assets
|
||||
step.Outputs = b.Outputs
|
||||
step.Secrets = []string{}
|
||||
|
||||
return step, nil
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package generate
|
||||
|
||||
type StartContext struct {
|
||||
BaseImage string
|
||||
Command string
|
||||
outputs []string
|
||||
paths []string
|
||||
variables map[string]string
|
||||
}
|
||||
|
||||
func NewStartContext() *StartContext {
|
||||
return &StartContext{
|
||||
variables: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StartContext) AddEnvVars(envVars map[string]string) {
|
||||
for k, v := range envVars {
|
||||
s.variables[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StartContext) AddPaths(paths []string) {
|
||||
s.paths = append(s.paths, paths...)
|
||||
}
|
||||
|
||||
func (s *StartContext) AddOutputs(outputs []string) {
|
||||
s.outputs = append(s.outputs, outputs...)
|
||||
}
|
||||
@@ -60,6 +60,12 @@ func NewExecCommand(cmd string, options ...ExecOptions) Command {
|
||||
}
|
||||
|
||||
func NewExecShellCommand(cmd string, options ...ExecOptions) Command {
|
||||
if len(options) == 0 {
|
||||
options = []ExecOptions{
|
||||
{CustomName: cmd},
|
||||
}
|
||||
}
|
||||
|
||||
exec := NewExecCommand("sh -c '"+cmd+"'", options...)
|
||||
return exec
|
||||
}
|
||||
|
||||
+18
-17
@@ -1,34 +1,35 @@
|
||||
package plan
|
||||
|
||||
const (
|
||||
RAILPACK_BUILDER_IMAGE = "ghcr.io/railwayapp/railpack-builder-base:latest"
|
||||
RAILPACK_RUNTIME_IMAGE = "ghcr.io/railwayapp/railpack-runtime-base:latest"
|
||||
)
|
||||
|
||||
type BuildPlan struct {
|
||||
BaseImage string `json:"baseImage,omitempty"`
|
||||
Steps []Step `json:"steps,omitempty"`
|
||||
Start Start `json:"start,omitempty"`
|
||||
Caches map[string]*Cache `json:"caches,omitempty"`
|
||||
Secrets []string `json:"secrets,omitempty"`
|
||||
Steps []Step `json:"steps,omitempty"`
|
||||
Caches map[string]*Cache `json:"caches,omitempty"`
|
||||
Secrets []string `json:"secrets,omitempty"`
|
||||
Deploy Deploy `json:"deploy,omitempty"`
|
||||
}
|
||||
|
||||
type Start struct {
|
||||
// The image to use for the container runtime
|
||||
BaseImage string `json:"baseImage,omitempty"`
|
||||
type Deploy struct {
|
||||
// The inputs for the deploy step
|
||||
Inputs []Input `json:"inputs,omitempty"`
|
||||
|
||||
// The command to run in the container
|
||||
Command string `json:"cmd,omitempty"`
|
||||
StartCmd string `json:"startCommand,omitempty"`
|
||||
|
||||
// Outputs to be copied from the container to the host
|
||||
Outputs []string `json:"outputs,omitempty"`
|
||||
|
||||
// $PATHs to be prefixed to the container's base $PATH
|
||||
Paths []string `json:"paths,omitempty"`
|
||||
|
||||
// Environment variables to set in the container. These are not available at build time.
|
||||
// The variables available to this step. The key is the name of the variable that is referenced in a variable command
|
||||
Variables map[string]string `json:"variables,omitempty"`
|
||||
|
||||
// The paths to prepend to the $PATH environment variable
|
||||
Paths []string `json:"paths,omitempty"`
|
||||
}
|
||||
|
||||
func NewBuildPlan() *BuildPlan {
|
||||
return &BuildPlan{
|
||||
Steps: []Step{},
|
||||
Start: Start{},
|
||||
Deploy: Deploy{},
|
||||
Caches: make(map[string]*Cache),
|
||||
Secrets: []string{},
|
||||
}
|
||||
|
||||
+59
-30
@@ -6,35 +6,68 @@ import (
|
||||
"github.com/invopop/jsonschema"
|
||||
)
|
||||
|
||||
type Input struct {
|
||||
Image string `json:"image,omitempty"`
|
||||
Step string `json:"step,omitempty"`
|
||||
Local bool `json:"local,omitempty"`
|
||||
Include []string `json:"include,omitempty"`
|
||||
Exclude []string `json:"exclude,omitempty"`
|
||||
}
|
||||
|
||||
type InputOptions struct {
|
||||
Include []string
|
||||
Exclude []string
|
||||
}
|
||||
|
||||
type Step struct {
|
||||
// The name of the step
|
||||
Name string `json:"name,omitempty" jsonschema:"description=The name of the step"`
|
||||
|
||||
// The steps that this step depends on. The step will only run after all the steps in DependsOn have run
|
||||
DependsOn []string `json:"dependsOn,omitempty" jsonschema:"description=The steps that this step depends on. The step will only run after all the steps in DependsOn have run"`
|
||||
|
||||
// The commands to run in this step
|
||||
Commands []Command `json:"commands,omitempty" jsonschema:"description=The commands to run in this step"`
|
||||
|
||||
// The secrets that this step uses
|
||||
Secrets []string `json:"secrets" jsonschema:"description=The secrets that this step uses"`
|
||||
|
||||
// Paths that this step outputs. Only these paths will be available to the next step
|
||||
Outputs []string `json:"outputs,omitempty" jsonschema:"description=Paths that this step outputs. Only these paths will be available to the next step"`
|
||||
|
||||
// The assets available to this step. The key is the name of the asset that is referenced in a file command
|
||||
Assets map[string]string `json:"assets,omitempty" jsonschema:"description=The assets available to this step. The key is the name of the asset that is referenced in a file command"`
|
||||
|
||||
// The variables available to this step. The key is the name of the variable that is referenced in a variable command
|
||||
Name string `json:"name,omitempty" jsonschema:"description=The name of the step"`
|
||||
Inputs []Input `json:"inputs,omitempty" jsonschema:"description=The inputs for this step"`
|
||||
Commands []Command `json:"commands,omitempty" jsonschema:"description=The commands to run in this step"`
|
||||
Secrets []string `json:"secrets,omitempty" jsonschema:"description=The secrets that this step uses"`
|
||||
Assets map[string]string `json:"assets,omitempty" jsonschema:"description=The assets available to this step. The key is the name of the asset that is referenced in a file command"`
|
||||
Variables map[string]string `json:"variables,omitempty" jsonschema:"description=The variables available to this step. The key is the name of the variable that is referenced in a variable command"`
|
||||
Caches []string `json:"caches,omitempty" jsonschema:"description=The caches available to all commands in this step. Each cache must refer to a cache at the top level of the plan"`
|
||||
}
|
||||
|
||||
// The caches available to all commands in this step. Each cache must refer to a cache at the top level of the plan
|
||||
Caches []string `json:"caches,omitempty" jsonschema:"description=The caches available to all commands in this step. Each cache must refer to a cache at the top level of the plan"`
|
||||
func NewStepInput(stepName string, options ...InputOptions) Input {
|
||||
input := Input{
|
||||
Step: stepName,
|
||||
}
|
||||
|
||||
// The base image that will be used for this step
|
||||
// If empty (default), the base image will be the one from the previous step
|
||||
// Only set this if you don't want to reuse any part of the file system from the previous step
|
||||
StartingImage string `json:"startingImage,omitempty" jsonschema:"description=The base image that will be used for this step. If empty (default), the base image will be the one from the previous step. Only set this if you don't want to reuse any part of the file system from the previous step"`
|
||||
if len(options) > 0 {
|
||||
input.Include = options[0].Include
|
||||
input.Exclude = options[0].Exclude
|
||||
}
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
func NewImageInput(image string, options ...InputOptions) Input {
|
||||
input := Input{
|
||||
Image: image,
|
||||
}
|
||||
|
||||
if len(options) > 0 {
|
||||
input.Include = options[0].Include
|
||||
input.Exclude = options[0].Exclude
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
func RuntimeImageInput() Input {
|
||||
return NewImageInput("ghcr.io/railwayapp/railpack-runtime-base:latest")
|
||||
}
|
||||
|
||||
func NewLocalInput(path string) Input {
|
||||
return Input{
|
||||
Local: true,
|
||||
Include: []string{path},
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Input) String() string {
|
||||
bytes, _ := json.Marshal(i)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func NewStep(name string) *Step {
|
||||
@@ -46,10 +79,6 @@ func NewStep(name string) *Step {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Step) DependOn(name string) {
|
||||
s.DependsOn = append(s.DependsOn, name)
|
||||
}
|
||||
|
||||
func (s *Step) AddCommands(commands []Command) {
|
||||
if s.Commands == nil {
|
||||
s.Commands = []Command{}
|
||||
@@ -89,7 +118,7 @@ func (Step) JSONSchemaExtend(schema *jsonschema.Schema) {
|
||||
var required []string
|
||||
for _, prop := range schema.Required {
|
||||
if prop != "name" {
|
||||
required = append(required, "name")
|
||||
required = append(required, prop)
|
||||
}
|
||||
}
|
||||
schema.Required = required
|
||||
|
||||
+3
-3
@@ -144,10 +144,10 @@ func FormatBuildResult(br *BuildResult, options ...PrintOptions) string {
|
||||
}
|
||||
}
|
||||
|
||||
if br.Plan.Start.Command != "" {
|
||||
output.WriteString(sectionHeaderStyle.MarginTop(1).Render("Start"))
|
||||
if br.Plan.Deploy.StartCmd != "" {
|
||||
output.WriteString(sectionHeaderStyle.MarginTop(1).Render("Deploy"))
|
||||
output.WriteString("\n")
|
||||
output.WriteString(fmt.Sprintf("%s %s", commandPrefixStyle.Render("$"), commandStyle.Render(br.Plan.Start.Command)))
|
||||
output.WriteString(fmt.Sprintf("%s %s", commandPrefixStyle.Render("$"), commandStyle.Render(br.Plan.Deploy.StartCmd)))
|
||||
}
|
||||
|
||||
if opts.Metadata && br.Metadata != nil && len(br.Metadata) > 0 {
|
||||
|
||||
@@ -13,7 +13,7 @@ const (
|
||||
DEFAULT_GO_VERSION = "1.23"
|
||||
GO_BUILD_CACHE_KEY = "go-build"
|
||||
GO_BINARY_NAME = "out"
|
||||
START_IMAGE = "alpine:latest"
|
||||
GO_PATH = "/go"
|
||||
)
|
||||
|
||||
type GoProvider struct{}
|
||||
@@ -31,35 +31,37 @@ func (p *GoProvider) Initialize(ctx *generate.GenerateContext) error {
|
||||
}
|
||||
|
||||
func (p *GoProvider) Plan(ctx *generate.GenerateContext) error {
|
||||
packages, err := p.Packages(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
builder := p.GetBuilder(ctx)
|
||||
p.InstallGoPackages(ctx, builder)
|
||||
|
||||
install, err := p.Install(ctx, packages)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddInput(plan.NewStepInput(builder.Name()))
|
||||
p.InstallGoDeps(ctx, install)
|
||||
|
||||
build, err := p.Build(ctx, packages, install)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddInput(plan.NewStepInput(install.Name()))
|
||||
p.Build(ctx, build)
|
||||
|
||||
if build != nil {
|
||||
ctx.Start.Command = fmt.Sprintf("./%s", GO_BINARY_NAME)
|
||||
ctx.Deploy.StartCmd = fmt.Sprintf("./%s", GO_BINARY_NAME)
|
||||
|
||||
if !p.hasCGOEnabled(ctx) {
|
||||
ctx.Start.AddOutputs([]string{GO_BINARY_NAME})
|
||||
if p.hasCGOEnabled(ctx) {
|
||||
runtimeAptStep := ctx.NewAptStepBuilder("runtime")
|
||||
runtimeAptStep.AddInput(ctx.DefaultRuntimeInputWithPackages([]string{"libc6", "tzdata"}))
|
||||
|
||||
ctx.Start.BaseImage = START_IMAGE
|
||||
if startImage, _ := ctx.Env.GetConfigVariable("START_IMAGE"); startImage != "" {
|
||||
ctx.Start.BaseImage = startImage
|
||||
}
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(runtimeAptStep.Name()),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
|
||||
if p.isGin(ctx) {
|
||||
ctx.Start.AddEnvVars(map[string]string{"GIN_MODE": "release"})
|
||||
} else {
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
ctx.DefaultRuntimeInputWithPackages([]string{"tzdata"}),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,52 +70,51 @@ func (p *GoProvider) Plan(ctx *generate.GenerateContext) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *GoProvider) Build(ctx *generate.GenerateContext, packages *generate.MiseStepBuilder, install *generate.CommandStepBuilder) (*generate.CommandStepBuilder, error) {
|
||||
func (p *GoProvider) Build(ctx *generate.GenerateContext, build *generate.CommandStepBuilder) {
|
||||
var buildCmd string
|
||||
|
||||
flags := "-w -s"
|
||||
baseBuildCmd := fmt.Sprintf("go build -ldflags=\"%s\" -o %s", flags, GO_BINARY_NAME)
|
||||
|
||||
if binName, _ := ctx.Env.GetConfigVariable("GO_BIN"); binName != "" {
|
||||
// If there is a RAILPACK_GO_BIN variable, use that
|
||||
buildCmd = fmt.Sprintf("go build -o %s ./cmd/%s", GO_BINARY_NAME, binName)
|
||||
buildCmd = fmt.Sprintf("%s ./cmd/%s", baseBuildCmd, binName)
|
||||
} else if p.isGoMod(ctx) && p.hasRootGoFiles(ctx) {
|
||||
buildCmd = fmt.Sprintf("go build -o %s", GO_BINARY_NAME)
|
||||
buildCmd = baseBuildCmd
|
||||
} else if dirs, err := ctx.App.FindDirectories("cmd/*"); err == nil && len(dirs) > 0 {
|
||||
// Try to find a command in the cmd directory
|
||||
cmdName := filepath.Base(dirs[0])
|
||||
buildCmd = fmt.Sprintf("go build -o %s ./cmd/%s", GO_BINARY_NAME, cmdName)
|
||||
buildCmd = fmt.Sprintf("%s ./cmd/%s", baseBuildCmd, cmdName)
|
||||
} else if p.isGoMod(ctx) {
|
||||
buildCmd = fmt.Sprintf("go build -o %s", GO_BINARY_NAME)
|
||||
buildCmd = baseBuildCmd
|
||||
} else if ctx.App.HasMatch("main.go") {
|
||||
buildCmd = fmt.Sprintf("go build -o %s main.go", GO_BINARY_NAME)
|
||||
buildCmd = fmt.Sprintf("%s main.go", baseBuildCmd)
|
||||
}
|
||||
|
||||
if buildCmd == "" {
|
||||
return nil, nil
|
||||
return
|
||||
}
|
||||
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddCache(p.goBuildCache(ctx))
|
||||
build.AddCommands([]plan.Command{
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecCommand(buildCmd),
|
||||
})
|
||||
|
||||
if packages != nil {
|
||||
build.DependsOn = append(build.DependsOn, packages.DisplayName)
|
||||
}
|
||||
|
||||
if install != nil {
|
||||
build.DependsOn = append(build.DependsOn, install.DisplayName)
|
||||
}
|
||||
|
||||
return build, nil
|
||||
}
|
||||
|
||||
func (p *GoProvider) Install(ctx *generate.GenerateContext, packages *generate.MiseStepBuilder) (*generate.CommandStepBuilder, error) {
|
||||
func (p *GoProvider) InstallGoDeps(ctx *generate.GenerateContext, install *generate.CommandStepBuilder) {
|
||||
install.AddEnvVars(map[string]string{
|
||||
"GOPATH": GO_PATH,
|
||||
"GOBIN": fmt.Sprintf("%s/bin", GO_PATH),
|
||||
})
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewPathCommand(fmt.Sprintf("%s/bin", GO_PATH)),
|
||||
})
|
||||
|
||||
if !p.isGoMod(ctx) {
|
||||
return nil, nil
|
||||
return
|
||||
}
|
||||
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddCache(p.goBuildCache(ctx))
|
||||
install.AddCommand(plan.NewCopyCommand("go.mod"))
|
||||
|
||||
@@ -123,24 +124,13 @@ func (p *GoProvider) Install(ctx *generate.GenerateContext, packages *generate.M
|
||||
|
||||
install.AddCommand(plan.NewExecCommand("go mod download"))
|
||||
|
||||
// If CGO is enabled, we need to install the gcc packages
|
||||
if p.hasCGOEnabled(ctx) {
|
||||
aptStep := ctx.NewAptStepBuilder("cgo")
|
||||
aptStep.Packages = []string{"gcc", "g++", "libc6-dev"}
|
||||
install.DependsOn = append(install.DependsOn, aptStep.DisplayName)
|
||||
} else {
|
||||
if !p.hasCGOEnabled(ctx) {
|
||||
install.AddEnvVars(map[string]string{"CGO_ENABLED": "0"})
|
||||
}
|
||||
|
||||
install.DependsOn = []string{packages.DisplayName}
|
||||
|
||||
return install, nil
|
||||
}
|
||||
|
||||
func (p *GoProvider) Packages(ctx *generate.GenerateContext) (*generate.MiseStepBuilder, error) {
|
||||
packages := ctx.GetMiseStepBuilder()
|
||||
|
||||
goPkg := packages.Default("go", DEFAULT_GO_VERSION)
|
||||
func (p *GoProvider) InstallGoPackages(ctx *generate.GenerateContext, miseStep *generate.MiseStepBuilder) {
|
||||
goPkg := miseStep.Default("go", DEFAULT_GO_VERSION)
|
||||
|
||||
if goModContents, err := ctx.App.ReadFile("go.mod"); err == nil {
|
||||
// Split content into lines and look for "go X.XX" line
|
||||
@@ -149,7 +139,7 @@ func (p *GoProvider) Packages(ctx *generate.GenerateContext) (*generate.MiseStep
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "go ") {
|
||||
// Extract version number
|
||||
if goVersion := strings.TrimSpace(strings.TrimPrefix(line, "go")); goVersion != "" {
|
||||
packages.Version(goPkg, goVersion, "go.mod")
|
||||
miseStep.Version(goPkg, goVersion, "go.mod")
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -157,10 +147,18 @@ func (p *GoProvider) Packages(ctx *generate.GenerateContext) (*generate.MiseStep
|
||||
}
|
||||
|
||||
if envVersion, varName := ctx.Env.GetConfigVariable("GO_VERSION"); envVersion != "" {
|
||||
packages.Version(goPkg, envVersion, varName)
|
||||
miseStep.Version(goPkg, envVersion, varName)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GoProvider) GetBuilder(ctx *generate.GenerateContext) *generate.MiseStepBuilder {
|
||||
miseStep := ctx.GetMiseStepBuilder()
|
||||
|
||||
if p.hasCGOEnabled(ctx) {
|
||||
miseStep.SupportingAptPackages = append(miseStep.SupportingAptPackages, "gcc", "g++", "libc6-dev")
|
||||
}
|
||||
|
||||
return packages, nil
|
||||
return miseStep
|
||||
}
|
||||
|
||||
func (p *GoProvider) addMetadata(ctx *generate.GenerateContext) {
|
||||
|
||||
+91
-107
@@ -2,6 +2,7 @@ package node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
@@ -18,8 +19,9 @@ const (
|
||||
)
|
||||
|
||||
type NodeProvider struct {
|
||||
packageJson *PackageJson
|
||||
workspace *Workspace
|
||||
packageJson *PackageJson
|
||||
packageManager PackageManager
|
||||
workspace *Workspace
|
||||
}
|
||||
|
||||
func (p *NodeProvider) Name() string {
|
||||
@@ -33,6 +35,8 @@ func (p *NodeProvider) Initialize(ctx *generate.GenerateContext) error {
|
||||
}
|
||||
p.packageJson = packageJson
|
||||
|
||||
p.packageManager = p.getPackageManager(ctx.App)
|
||||
|
||||
workspace, err := NewWorkspace(ctx.App)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -51,56 +55,70 @@ func (p *NodeProvider) Plan(ctx *generate.GenerateContext) error {
|
||||
return fmt.Errorf("package.json not loaded, did you call Initialize?")
|
||||
}
|
||||
|
||||
packages, err := p.Packages(ctx, p.packageJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
miseStep := ctx.GetMiseStepBuilder()
|
||||
p.InstallMisePackages(ctx, miseStep)
|
||||
|
||||
install, err := p.Install(ctx, packages, p.packageJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Install
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddInput(plan.NewStepInput(miseStep.Name()))
|
||||
p.InstallNodeDeps(ctx, install)
|
||||
|
||||
if _, err := p.Build(ctx, install, p.packageJson); err != nil {
|
||||
return err
|
||||
}
|
||||
// Prune
|
||||
prune := ctx.NewCommandStep("prune")
|
||||
prune.AddInput(plan.NewStepInput(install.Name()))
|
||||
p.PruneNodeDeps(ctx, prune)
|
||||
|
||||
if err := p.start(ctx, p.packageJson); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *NodeProvider) start(ctx *generate.GenerateContext, packageJson *PackageJson) error {
|
||||
packageManager := p.getPackageManager(ctx.App)
|
||||
|
||||
if start := p.getScripts(packageJson, "start"); start != "" {
|
||||
ctx.Start.Command = packageManager.RunCmd("start")
|
||||
} else if main := packageJson.Main; main != "" {
|
||||
ctx.Start.Command = packageManager.RunScriptCommand(main)
|
||||
} else if files, err := ctx.App.FindFiles("{index.js,index.ts}"); err == nil && len(files) > 0 {
|
||||
ctx.Start.Command = packageManager.RunScriptCommand(files[0])
|
||||
}
|
||||
|
||||
ctx.Start.AddOutputs([]string{"."})
|
||||
ctx.Start.AddEnvVars(p.GetNodeEnvVars(ctx))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *NodeProvider) Build(ctx *generate.GenerateContext, install *generate.CommandStepBuilder, packageJson *PackageJson) (*generate.CommandStepBuilder, error) {
|
||||
packageManager := p.getPackageManager(ctx.App)
|
||||
// Build
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.DependsOn = []string{install.DisplayName}
|
||||
build.AddInput(plan.NewStepInput(install.Name()))
|
||||
p.Build(ctx, build)
|
||||
|
||||
_, ok := packageJson.Scripts["build"]
|
||||
// Deploy
|
||||
ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
|
||||
maps.Copy(ctx.Deploy.Variables, p.GetNodeEnvVars(ctx))
|
||||
|
||||
buildIncludeDirs := []string{"."}
|
||||
if p.usesCorepack() {
|
||||
buildIncludeDirs = append(buildIncludeDirs, "/root/.cache")
|
||||
}
|
||||
|
||||
ctx.Deploy.Inputs = append(ctx.Deploy.Inputs, []plan.Input{
|
||||
ctx.DefaultRuntimeInput(),
|
||||
plan.NewStepInput(miseStep.Name(), plan.InputOptions{
|
||||
Include: miseStep.GetOutputPaths(),
|
||||
}),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: buildIncludeDirs,
|
||||
Exclude: []string{"node_modules"},
|
||||
}),
|
||||
plan.NewStepInput(prune.Name(), plan.InputOptions{
|
||||
Include: []string{"/app/node_modules"}, // we only wanted the pruned node_modules
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *NodeProvider) GetStartCommand(ctx *generate.GenerateContext) string {
|
||||
if start := p.getScripts(p.packageJson, "start"); start != "" {
|
||||
return p.packageManager.RunCmd("start")
|
||||
} else if main := p.packageJson.Main; main != "" {
|
||||
return p.packageManager.RunScriptCommand(main)
|
||||
} else if files, err := ctx.App.FindFiles("{index.js,index.ts}"); err == nil && len(files) > 0 {
|
||||
return p.packageManager.RunScriptCommand(files[0])
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *NodeProvider) Build(ctx *generate.GenerateContext, build *generate.CommandStepBuilder) {
|
||||
_, ok := p.packageJson.Scripts["build"]
|
||||
if ok {
|
||||
build.AddCommands([]plan.Command{
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecCommand(packageManager.RunCmd("build")),
|
||||
plan.NewExecCommand(p.packageManager.RunCmd("build")),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// Generic node_modules cache
|
||||
@@ -115,97 +133,63 @@ func (p *NodeProvider) Build(ctx *generate.GenerateContext, install *generate.Co
|
||||
build.AddCache(ctx.Caches.AddCache(fmt.Sprintf("next-%s", nextApp), nextCacheDir))
|
||||
}
|
||||
}
|
||||
|
||||
return build, nil
|
||||
}
|
||||
|
||||
func (p *NodeProvider) Install(ctx *generate.GenerateContext, packages *generate.MiseStepBuilder, packageJson *PackageJson) (*generate.CommandStepBuilder, error) {
|
||||
lenDeps := len(packageJson.Dependencies) + len(packageJson.DevDependencies)
|
||||
|
||||
setup, err := p.Setup(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (p *NodeProvider) PruneNodeDeps(ctx *generate.GenerateContext, prune *generate.CommandStepBuilder) {
|
||||
if ctx.Env.IsConfigVariableTruthy("NO_PRUNE") {
|
||||
return
|
||||
}
|
||||
|
||||
if lenDeps == 0 {
|
||||
return setup, nil
|
||||
}
|
||||
prune.Variables["NPM_CONFIG_PRODUCTION"] = "true"
|
||||
prune.Secrets = []string{}
|
||||
p.packageManager.PruneDeps(ctx, prune)
|
||||
}
|
||||
|
||||
var corepackStepName string
|
||||
if p.usesCorepack(packageJson) {
|
||||
corepackStep := ctx.NewCommandStep("corepack")
|
||||
corepackStep.AddCommands([]plan.Command{
|
||||
func (p *NodeProvider) InstallNodeDeps(ctx *generate.GenerateContext, install *generate.CommandStepBuilder) {
|
||||
maps.Copy(install.Variables, p.GetNodeEnvVars(ctx))
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"NODE", "NPM", "BUN", "PNPM", "YARN", "CI"})
|
||||
install.AddPaths([]string{"/app/node_modules/.bin"})
|
||||
|
||||
if p.usesCorepack() {
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewCopyCommand("package.json"),
|
||||
plan.NewExecCommand("corepack enable"),
|
||||
plan.NewExecCommand("corepack prepare --activate"),
|
||||
})
|
||||
corepackStepName = corepackStep.DisplayName
|
||||
corepackStep.DependsOn = append(corepackStep.DependsOn, setup.DisplayName)
|
||||
corepackStep.Secrets = []string{} // Don't include any secrets in this step
|
||||
}
|
||||
|
||||
pkgManager := p.getPackageManager(ctx.App)
|
||||
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.DependsOn = append(install.DependsOn, []string{packages.DisplayName, setup.DisplayName}...)
|
||||
|
||||
// We only want to invalidate the install step when these secrets change, not all of them
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"NODE", "NPM", "BUN", "PNPM", "YARN", "CI"})
|
||||
|
||||
pkgManager.installDependencies(ctx, packageJson, install)
|
||||
|
||||
if corepackStepName != "" {
|
||||
install.DependsOn = append(install.DependsOn, corepackStepName)
|
||||
}
|
||||
|
||||
return install, nil
|
||||
p.packageManager.installDependencies(ctx, p.packageJson, install)
|
||||
}
|
||||
|
||||
func (p *NodeProvider) Setup(ctx *generate.GenerateContext) (*generate.CommandStepBuilder, error) {
|
||||
setup := ctx.NewCommandStep("setup")
|
||||
setup.AddEnvVars(p.GetNodeEnvVars(ctx))
|
||||
setup.AddPaths([]string{"/app/node_modules/.bin"})
|
||||
setup.Secrets = []string{}
|
||||
|
||||
return setup, nil
|
||||
}
|
||||
|
||||
func (p *NodeProvider) Packages(ctx *generate.GenerateContext, packageJson *PackageJson) (*generate.MiseStepBuilder, error) {
|
||||
packageManager := p.getPackageManager(ctx.App)
|
||||
ctx.Metadata.Set("packageManager", string(packageManager))
|
||||
|
||||
packages := ctx.GetMiseStepBuilder()
|
||||
|
||||
func (p *NodeProvider) InstallMisePackages(ctx *generate.GenerateContext, miseStep *generate.MiseStepBuilder) {
|
||||
// Node
|
||||
if packageManager.requiresNode(packageJson) {
|
||||
node := packages.Default("node", DEFAULT_NODE_VERSION)
|
||||
if p.packageManager.requiresNode(p.packageJson) {
|
||||
node := miseStep.Default("node", DEFAULT_NODE_VERSION)
|
||||
|
||||
if envVersion, varName := ctx.Env.GetConfigVariable("NODE_VERSION"); envVersion != "" {
|
||||
packages.Version(node, envVersion, varName)
|
||||
miseStep.Version(node, envVersion, varName)
|
||||
}
|
||||
|
||||
if packageJson.Engines != nil && packageJson.Engines["node"] != "" {
|
||||
packages.Version(node, packageJson.Engines["node"], "package.json > engines > node")
|
||||
if p.packageJson.Engines != nil && p.packageJson.Engines["node"] != "" {
|
||||
miseStep.Version(node, p.packageJson.Engines["node"], "package.json > engines > node")
|
||||
}
|
||||
}
|
||||
|
||||
// Bun
|
||||
if packageManager == PackageManagerBun {
|
||||
bun := packages.Default("bun", DEFAULT_BUN_VERSION)
|
||||
if p.packageManager == PackageManagerBun {
|
||||
bun := miseStep.Default("bun", DEFAULT_BUN_VERSION)
|
||||
|
||||
if envVersion, varName := ctx.Env.GetConfigVariable("BUN_VERSION"); envVersion != "" {
|
||||
packages.Version(bun, envVersion, varName)
|
||||
miseStep.Version(bun, envVersion, varName)
|
||||
}
|
||||
}
|
||||
|
||||
packageManager.GetPackageManagerPackages(ctx, packages)
|
||||
p.packageManager.GetPackageManagerPackages(ctx, miseStep)
|
||||
|
||||
if p.usesCorepack(packageJson) {
|
||||
packages.Variables["MISE_NODE_COREPACK"] = "true"
|
||||
if p.usesCorepack() {
|
||||
miseStep.Variables["MISE_NODE_COREPACK"] = "true"
|
||||
}
|
||||
|
||||
return packages, nil
|
||||
}
|
||||
|
||||
func (p *NodeProvider) GetNodeEnvVars(ctx *generate.GenerateContext) map[string]string {
|
||||
@@ -221,8 +205,8 @@ func (p *NodeProvider) GetNodeEnvVars(ctx *generate.GenerateContext) map[string]
|
||||
return envVars
|
||||
}
|
||||
|
||||
func (p *NodeProvider) usesCorepack(packageJson *PackageJson) bool {
|
||||
return packageJson.PackageManager != nil
|
||||
func (p *NodeProvider) usesCorepack() bool {
|
||||
return p.packageJson.PackageManager != nil
|
||||
}
|
||||
|
||||
func (p *NodeProvider) getPackageManager(app *app.App) PackageManager {
|
||||
|
||||
@@ -102,11 +102,10 @@ func TestNodeCorepack(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := testingUtils.CreateGenerateContext(t, tt.path)
|
||||
provider := NodeProvider{}
|
||||
|
||||
packageJson, err := provider.GetPackageJson(ctx.App)
|
||||
err := provider.Initialize(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
usesCorepack := provider.usesCorepack(packageJson)
|
||||
usesCorepack := provider.usesCorepack()
|
||||
require.Equal(t, tt.wantCorepack, usesCorepack)
|
||||
})
|
||||
}
|
||||
@@ -139,6 +138,8 @@ func TestGetNextApps(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := testingUtils.CreateGenerateContext(t, tt.path)
|
||||
provider := NodeProvider{}
|
||||
err := provider.Initialize(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
nextApps, err := provider.getNextApps(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -64,12 +64,30 @@ func (p PackageManager) installDependencies(ctx *generate.GenerateContext, packa
|
||||
p.InstallDeps(ctx, install)
|
||||
}
|
||||
|
||||
// GetCache returns the cache for the package manager
|
||||
func (p PackageManager) GetInstallCache(ctx *generate.GenerateContext) string {
|
||||
switch p {
|
||||
case PackageManagerNpm:
|
||||
return ctx.Caches.AddCache("npm-install", "/root/.npm")
|
||||
case PackageManagerPnpm:
|
||||
return ctx.Caches.AddCache("pnpm-install", "/root/.local/share/pnpm/store/v3")
|
||||
case PackageManagerBun:
|
||||
return ctx.Caches.AddCache("bun-install", "/root/.bun/install/cache")
|
||||
case PackageManagerYarn1:
|
||||
return ctx.Caches.AddCacheWithType("yarn-install", "/usr/local/share/.cache/yarn", plan.CacheTypeLocked)
|
||||
case PackageManagerYarn2:
|
||||
return ctx.Caches.AddCache("yarn-install", "/usr/local/share/.cache/yarn")
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (p PackageManager) InstallDeps(ctx *generate.GenerateContext, install *generate.CommandStepBuilder) {
|
||||
install.AddCache(p.GetInstallCache(ctx))
|
||||
|
||||
switch p {
|
||||
case PackageManagerNpm:
|
||||
hasLockfile := ctx.App.HasMatch("package-lock.json")
|
||||
install.AddCache(ctx.Caches.AddCache("npm-install", "/root/.npm"))
|
||||
|
||||
if hasLockfile {
|
||||
install.AddCommand(plan.NewExecCommand("npm ci"))
|
||||
} else {
|
||||
@@ -77,17 +95,30 @@ func (p PackageManager) InstallDeps(ctx *generate.GenerateContext, install *gene
|
||||
}
|
||||
case PackageManagerPnpm:
|
||||
install.AddCommand(plan.NewExecCommand("pnpm install --frozen-lockfile --prod=false"))
|
||||
install.AddCache(ctx.Caches.AddCache("pnpm-install", "/root/.local/share/pnpm/store/v3"))
|
||||
case PackageManagerBun:
|
||||
install.AddCommand(plan.NewExecCommand("bun install --frozen-lockfile"))
|
||||
// TODO: We should also cache this for the build step
|
||||
install.AddCache(ctx.Caches.AddCache("bun-install", "/root/.bun/install/cache"))
|
||||
case PackageManagerYarn1:
|
||||
install.AddCommand(plan.NewExecCommand("yarn install --frozen-lockfile"))
|
||||
install.AddCache(ctx.Caches.AddCacheWithType("yarn-install", "/usr/local/share/.cache/yarn", plan.CacheTypeLocked))
|
||||
case PackageManagerYarn2:
|
||||
install.AddCommand(plan.NewExecCommand("yarn install --check-cache"))
|
||||
install.AddCache(ctx.Caches.AddCache("yarn-install", "/usr/local/share/.cache/yarn"))
|
||||
}
|
||||
}
|
||||
|
||||
func (p PackageManager) PruneDeps(ctx *generate.GenerateContext, prune *generate.CommandStepBuilder) {
|
||||
prune.AddCache(p.GetInstallCache(ctx))
|
||||
|
||||
switch p {
|
||||
case PackageManagerNpm:
|
||||
prune.AddCommand(plan.NewExecCommand("npm prune --omit=dev"))
|
||||
case PackageManagerPnpm:
|
||||
prune.AddCommand(plan.NewExecCommand("pnpm prune --prod"))
|
||||
case PackageManagerBun:
|
||||
// Prune is not supported in Bun. https://github.com/oven-sh/bun/issues/3605
|
||||
prune.AddCommand(plan.NewExecShellCommand("rm -rf node_modules && bun install --production"))
|
||||
case PackageManagerYarn1:
|
||||
prune.AddCommand(plan.NewExecCommand("yarn install --production=true"))
|
||||
case PackageManagerYarn2:
|
||||
prune.AddCommand(plan.NewExecCommand("yarn install --production=true"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +133,6 @@ func (p PackageManager) SupportingInstallFiles(app *a.App) []string {
|
||||
"**/bun.lockb",
|
||||
"**/bun.lock",
|
||||
"**/yarn.lock",
|
||||
"**/node_modules",
|
||||
"**/.pnp.*", // Yarn Plug'n'Play files
|
||||
"**/.yarnrc.yml", // Yarn 2+ config
|
||||
"**/.npmrc", // NPM config
|
||||
@@ -158,8 +188,10 @@ func (p PackageManager) GetPackageManagerPackages(ctx *generate.GenerateContext,
|
||||
}
|
||||
}
|
||||
|
||||
// Check is Node is required for the package manager
|
||||
// If the package manager is Bun, we avoid using Node unless it's specified in the package.json
|
||||
func (p PackageManager) requiresNode(packageJson *PackageJson) bool {
|
||||
if p != PackageManagerBun || packageJson == nil {
|
||||
if p != PackageManagerBun || packageJson == nil || packageJson.PackageManager != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+92
-65
@@ -32,65 +32,15 @@ func (p *PhpProvider) Initialize(ctx *generate.GenerateContext) error {
|
||||
}
|
||||
|
||||
func (p *PhpProvider) Plan(ctx *generate.GenerateContext) error {
|
||||
imageStep, err := p.phpImagePackage(ctx)
|
||||
phpImageStep, err := p.phpImagePackage(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Install nginx
|
||||
nginxPackages := ctx.NewAptStepBuilder("nginx")
|
||||
nginxPackages.Packages = []string{"nginx", "git", "zip", "unzip"}
|
||||
nginxPackages.DependsOn = []string{imageStep.DisplayName}
|
||||
|
||||
// Install composer
|
||||
if _, err := p.readComposerJson(ctx); err == nil {
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddCache(ctx.Caches.AddCache("composer", "/opt/cache/composer"))
|
||||
install.AddEnvVars(map[string]string{"COMPOSER_CACHE_DIR": "/opt/cache/composer"})
|
||||
|
||||
install.AddCommands([]plan.Command{
|
||||
// Copy composer from the composer image
|
||||
plan.CopyCommand{Image: "composer:latest", Src: "/usr/bin/composer", Dest: "/usr/bin/composer"},
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecCommand("composer install --ignore-platform-reqs"),
|
||||
})
|
||||
|
||||
install.DependsOn = []string{nginxPackages.DisplayName}
|
||||
}
|
||||
|
||||
// Install node
|
||||
nodeProvider := node.NodeProvider{}
|
||||
isNode := ctx.App.HasMatch("package.json")
|
||||
if packageJson, err := nodeProvider.GetPackageJson(ctx.App); isNode && err == nil && packageJson != nil {
|
||||
ctx.EnterSubContext("node")
|
||||
|
||||
nodePackages, err := nodeProvider.Packages(ctx, packageJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// nodePackages.DependsOn = []string{imageStep.DisplayName}
|
||||
|
||||
nodeInstall, err := nodeProvider.Install(ctx, nodePackages, packageJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeBuild, err := nodeProvider.Build(ctx, nodeInstall, packageJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Only copy the changes to the app, not the entire rest of the file system
|
||||
nodeBuild.Outputs = []string{"/app"}
|
||||
|
||||
ctx.ExitSubContext()
|
||||
}
|
||||
|
||||
// Setup nginx
|
||||
nginxSetup := ctx.NewCommandStep("nginx:setup")
|
||||
nginxSetup.DependsOn = []string{nginxPackages.DisplayName}
|
||||
|
||||
nginxSetup.AddCommands([]plan.Command{
|
||||
// Nginx
|
||||
nginx := ctx.NewCommandStep("nginx")
|
||||
nginx.AddInput(plan.NewStepInput(phpImageStep.Name()))
|
||||
nginx.AddCommands([]plan.Command{
|
||||
plan.NewFileCommand("/etc/nginx/railpack.conf", "nginx.conf", plan.FileOptions{CustomName: "create nginx config"}),
|
||||
plan.NewExecCommand("nginx -t -c /etc/nginx/railpack.conf"),
|
||||
plan.NewFileCommand("/etc/php-fpm.conf", "php-fpm.conf", plan.FileOptions{CustomName: "create php-fpm config"}),
|
||||
@@ -100,22 +50,93 @@ func (p *PhpProvider) Plan(ctx *generate.GenerateContext) error {
|
||||
}),
|
||||
})
|
||||
|
||||
if p.usesLaravel(ctx) {
|
||||
nginxSetup.AddEnvVars(map[string]string{"IS_LARAVEL": "true"})
|
||||
}
|
||||
|
||||
nginxSetup.Assets["start-nginx.sh"] = startNginxScriptAsset
|
||||
nginx.Assets["start-nginx.sh"] = startNginxScriptAsset
|
||||
configFiles, err := p.getConfigFiles(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get config files: %w", err)
|
||||
}
|
||||
|
||||
nginxSetup.Assets["nginx.conf"] = configFiles.NginxConf
|
||||
nginxSetup.Assets["nginx.conf"] = configFiles.NginxConf
|
||||
nginxSetup.Assets["php-fpm.conf"] = configFiles.PhpFpmConf
|
||||
nginx.Assets["nginx.conf"] = configFiles.NginxConf
|
||||
nginx.Assets["nginx.conf"] = configFiles.NginxConf
|
||||
nginx.Assets["php-fpm.conf"] = configFiles.PhpFpmConf
|
||||
|
||||
ctx.Start.Command = "bash /start-nginx.sh"
|
||||
ctx.Start.AddOutputs([]string{"."})
|
||||
// Composer
|
||||
composer := ctx.NewCommandStep("install:composer")
|
||||
composer.AddInput(plan.NewStepInput(nginx.Name()))
|
||||
if _, err := p.readComposerJson(ctx); err == nil {
|
||||
composer.AddCache(ctx.Caches.AddCache("composer", "/opt/cache/composer"))
|
||||
composer.AddEnvVars(map[string]string{"COMPOSER_CACHE_DIR": "/opt/cache/composer"})
|
||||
|
||||
composer.AddCommands([]plan.Command{
|
||||
// Copy composer from the composer image
|
||||
plan.CopyCommand{Image: "composer:latest", Src: "/usr/bin/composer", Dest: "/usr/bin/composer"},
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecCommand("composer install --ignore-platform-reqs"),
|
||||
})
|
||||
}
|
||||
|
||||
// Node (if necessary)
|
||||
nodeProvider := node.NodeProvider{}
|
||||
isNode, err := nodeProvider.Detect(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isNode {
|
||||
err = nodeProvider.Initialize(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
miseStep := ctx.GetMiseStepBuilder()
|
||||
nodeProvider.InstallMisePackages(ctx, miseStep)
|
||||
|
||||
install := ctx.NewCommandStep("install:node")
|
||||
install.AddInput(plan.NewStepInput(miseStep.Name()))
|
||||
nodeProvider.InstallNodeDeps(ctx, install)
|
||||
|
||||
prune := ctx.NewCommandStep("prune:node")
|
||||
prune.AddInput(plan.NewStepInput(install.Name()))
|
||||
nodeProvider.PruneNodeDeps(ctx, prune)
|
||||
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.Inputs = []plan.Input{
|
||||
plan.NewStepInput(composer.Name()),
|
||||
|
||||
// Include the app and mise packages (node, pnpm, etc.)
|
||||
plan.NewStepInput(install.Name(), plan.InputOptions{
|
||||
Include: append([]string{"."}, miseStep.GetOutputPaths()...),
|
||||
}),
|
||||
}
|
||||
nodeProvider.Build(ctx, build)
|
||||
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(composer.Name()),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
Exclude: []string{"node_modules"},
|
||||
}),
|
||||
plan.NewStepInput(prune.Name(), plan.InputOptions{
|
||||
Include: []string{"/app/node_modules"},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
} else {
|
||||
// A manual build command will go here
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddInput(plan.NewStepInput(composer.Name()))
|
||||
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(build.Name()),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Deploy.StartCmd = "bash /start-nginx.sh"
|
||||
|
||||
if p.usesLaravel(ctx) {
|
||||
ctx.Deploy.Variables["IS_LARAVEL"] = "true"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -168,6 +189,12 @@ func (p *PhpProvider) phpImagePackage(ctx *generate.GenerateContext) (*generate.
|
||||
return getPhpImage(DEFAULT_PHP_VERSION)
|
||||
})
|
||||
|
||||
imageStep.AptPackages = append(imageStep.AptPackages, "nginx", "git", "zip", "unzip")
|
||||
|
||||
// Include both build and runtime apt packages since we don't have a separate runtime image
|
||||
imageStep.AptPackages = append(imageStep.AptPackages, ctx.Config.BuildAptPackages...)
|
||||
imageStep.AptPackages = append(imageStep.AptPackages, ctx.Config.Deploy.AptPackages...)
|
||||
|
||||
php := imageStep.Default("php", DEFAULT_PHP_VERSION)
|
||||
|
||||
// Read composer.json to get the PHP version
|
||||
|
||||
@@ -22,9 +22,9 @@ func (p *ProcfileProvider) Plan(ctx *generate.GenerateContext) (bool, error) {
|
||||
workerCommand := parsedProcfile["worker"]
|
||||
|
||||
if webCommand != "" {
|
||||
ctx.Start.Command = webCommand
|
||||
ctx.Deploy.StartCmd = webCommand
|
||||
} else if workerCommand != "" {
|
||||
ctx.Start.Command = workerCommand
|
||||
ctx.Deploy.StartCmd = workerCommand
|
||||
}
|
||||
|
||||
return false, nil
|
||||
|
||||
@@ -14,5 +14,5 @@ func TestProcfile(t *testing.T) {
|
||||
_, err := provider.Plan(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "gunicorn --bind 0.0.0.0:3333 main:app", ctx.Start.Command)
|
||||
require.Equal(t, "gunicorn --bind 0.0.0.0:3333 main:app", ctx.Deploy.StartCmd)
|
||||
}
|
||||
|
||||
+299
-58
@@ -1,6 +1,8 @@
|
||||
package python
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@@ -12,6 +14,9 @@ const (
|
||||
DEFAULT_PYTHON_VERSION = "3.13.2"
|
||||
UV_CACHE_DIR = "/opt/uv-cache"
|
||||
PIP_CACHE_DIR = "/opt/pip-cache"
|
||||
PACKAGES_DIR = "/opt/python-packages"
|
||||
VENV_PATH = "/app/.venv"
|
||||
LOCAL_BIN_PATH = "/root/.local/bin"
|
||||
)
|
||||
|
||||
type PythonProvider struct{}
|
||||
@@ -35,40 +40,294 @@ func (p *PythonProvider) Detect(ctx *generate.GenerateContext) (bool, error) {
|
||||
}
|
||||
|
||||
func (p *PythonProvider) Plan(ctx *generate.GenerateContext) error {
|
||||
if err := p.packages(ctx); err != nil {
|
||||
return err
|
||||
p.InstallMisePackages(ctx, ctx.GetMiseStepBuilder())
|
||||
|
||||
if p.hasRequirements(ctx) {
|
||||
p.PlanPip(ctx)
|
||||
} else if p.hasPyproject(ctx) && p.hasUv(ctx) {
|
||||
p.PlanUv(ctx)
|
||||
} else if p.hasPyproject(ctx) && p.hasPoetry(ctx) {
|
||||
p.PlanPoetry(ctx)
|
||||
} else if p.hasPyproject(ctx) && p.hasPdm(ctx) {
|
||||
p.PlanPDM(ctx)
|
||||
} else if p.hasPipfile(ctx) {
|
||||
p.PlanPipenv(ctx)
|
||||
}
|
||||
|
||||
if err := p.install(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
// Install dependencies
|
||||
// install := ctx.NewCommandStep("install")
|
||||
// install.AddInput(plan.NewStepInput(miseStep.Name()))
|
||||
// p.InstallPythonDeps(ctx, install)
|
||||
|
||||
if err := p.start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
// // Build step (if needed)
|
||||
// build := ctx.NewCommandStep("build")
|
||||
// build.AddInput(plan.NewStepInput(install.Name()))
|
||||
|
||||
// // Deploy configuration
|
||||
// ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
|
||||
// maps.Copy(ctx.Deploy.Variables, p.GetPythonEnvVars(ctx))
|
||||
|
||||
// ctx.Deploy.Inputs = append(ctx.Deploy.Inputs, []plan.Input{
|
||||
// plan.NewImageInput(plan.RAILPACK_RUNTIME_IMAGE),
|
||||
// plan.NewStepInput(miseStep.Name(), plan.InputOptions{
|
||||
// Include: miseStep.GetOutputPaths(),
|
||||
// }),
|
||||
// plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
// Include: []string{"."},
|
||||
// }),
|
||||
// plan.NewLocalInput("."),
|
||||
// }...)
|
||||
|
||||
p.addMetadata(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PythonProvider) start(ctx *generate.GenerateContext) error {
|
||||
ctx.Start.AddOutputs([]string{"."})
|
||||
|
||||
var startCommand string
|
||||
|
||||
func (p *PythonProvider) GetStartCommand(ctx *generate.GenerateContext) string {
|
||||
if ctx.App.HasMatch("main.py") {
|
||||
startCommand = "python main.py"
|
||||
return "python main.py"
|
||||
}
|
||||
|
||||
if startCommand != "" {
|
||||
ctx.Start.Command = startCommand
|
||||
}
|
||||
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *PythonProvider) install(ctx *generate.GenerateContext) error {
|
||||
func (p *PythonProvider) PlanUv(ctx *generate.GenerateContext) {
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddInput(plan.NewStepInput(p.GetBuilderDeps(ctx).Name()))
|
||||
|
||||
install.AddCache(ctx.Caches.AddCache("uv", UV_CACHE_DIR))
|
||||
install.AddEnvVars(map[string]string{
|
||||
"UV_COMPILE_BYTECODE": "1",
|
||||
"UV_LINK_MODE": "copy",
|
||||
"UV_CACHE_DIR": UV_CACHE_DIR,
|
||||
"UV_PYTHON_DOWNLOADS": "never",
|
||||
})
|
||||
install.AddEnvVars(p.GetPythonEnvVars(ctx))
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewExecCommand("pipx install uv"),
|
||||
plan.NewPathCommand(LOCAL_BIN_PATH),
|
||||
plan.NewCopyCommand("pyproject.toml"),
|
||||
plan.NewCopyCommand("uv.lock"),
|
||||
plan.NewExecCommand("uv sync --locked --no-dev --no-install-project"),
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecCommand("uv sync --locked --no-dev --no-editable"),
|
||||
plan.NewPathCommand(VENV_PATH + "/bin"),
|
||||
})
|
||||
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddInput(plan.NewStepInput(install.Name()))
|
||||
|
||||
ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
|
||||
maps.Copy(ctx.Deploy.Variables, p.GetPythonEnvVars(ctx))
|
||||
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(p.GetImageWithRuntimeDeps(ctx).Name()),
|
||||
plan.NewStepInput(ctx.GetMiseStepBuilder().Name(), plan.InputOptions{
|
||||
Include: ctx.GetMiseStepBuilder().GetOutputPaths(),
|
||||
}),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PythonProvider) PlanPipenv(ctx *generate.GenerateContext) {
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddInput(plan.NewStepInput(p.GetBuilderDeps(ctx).Name()))
|
||||
|
||||
install.AddEnvVars(p.GetPythonEnvVars(ctx))
|
||||
install.AddEnvVars(map[string]string{
|
||||
"PIPENV_CHECK_UPDATE": "false",
|
||||
"PIPENV_VENV_IN_PROJECT": "1",
|
||||
"PIPENV_IGNORE_VIRTUALENVS": "1",
|
||||
})
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"PYTHON", "PIP"})
|
||||
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewExecCommand("pipx install pipenv"),
|
||||
plan.NewPathCommand(LOCAL_BIN_PATH),
|
||||
plan.NewCopyCommand("Pipfile"),
|
||||
plan.NewCopyCommand("Pipfile.lock"),
|
||||
plan.NewExecCommand("pipenv install --deploy --ignore-pipfile"),
|
||||
plan.NewPathCommand(VENV_PATH + "/bin"),
|
||||
})
|
||||
|
||||
if ctx.App.HasMatch("Pipfile.lock") {
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewCopyCommand("Pipfile"),
|
||||
plan.NewCopyCommand("Pipfile.lock"),
|
||||
plan.NewExecCommand("pipenv install --deploy --ignore-pipfile"),
|
||||
})
|
||||
} else {
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewCopyCommand("Pipfile"),
|
||||
plan.NewExecCommand("pipenv install --skip-lock"),
|
||||
})
|
||||
}
|
||||
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewPathCommand(VENV_PATH + "/bin"),
|
||||
})
|
||||
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddInput(plan.NewStepInput(install.Name()))
|
||||
|
||||
ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
|
||||
maps.Copy(ctx.Deploy.Variables, p.GetPythonEnvVars(ctx))
|
||||
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(p.GetImageWithRuntimeDeps(ctx).Name()),
|
||||
plan.NewStepInput(ctx.GetMiseStepBuilder().Name(), plan.InputOptions{
|
||||
Include: ctx.GetMiseStepBuilder().GetOutputPaths(),
|
||||
}),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PythonProvider) PlanPDM(ctx *generate.GenerateContext) {
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddInput(plan.NewStepInput(p.GetBuilderDeps(ctx).Name()))
|
||||
|
||||
install.AddEnvVars(p.GetPythonEnvVars(ctx))
|
||||
install.AddEnvVars(map[string]string{
|
||||
"PDM_CHECK_UPDATE": "false",
|
||||
})
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"PYTHON", "PDM"})
|
||||
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewExecCommand("pipx install pdm"),
|
||||
plan.NewPathCommand(LOCAL_BIN_PATH),
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewExecCommand("python --version"),
|
||||
plan.NewExecCommand("pdm install --check --prod --no-editable"),
|
||||
plan.NewPathCommand(VENV_PATH + "/bin"),
|
||||
})
|
||||
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddInput(plan.NewStepInput(install.Name()))
|
||||
|
||||
ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
|
||||
maps.Copy(ctx.Deploy.Variables, p.GetPythonEnvVars(ctx))
|
||||
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(p.GetImageWithRuntimeDeps(ctx).Name()),
|
||||
plan.NewStepInput(ctx.GetMiseStepBuilder().Name(), plan.InputOptions{
|
||||
Include: ctx.GetMiseStepBuilder().GetOutputPaths(),
|
||||
}),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PythonProvider) PlanPoetry(ctx *generate.GenerateContext) {
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddInput(plan.NewStepInput(p.GetBuilderDeps(ctx).Name()))
|
||||
|
||||
install.AddEnvVars(p.GetPythonEnvVars(ctx))
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"PYTHON", "POETRY"})
|
||||
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewExecCommand("pipx install poetry"),
|
||||
plan.NewPathCommand(LOCAL_BIN_PATH),
|
||||
plan.NewExecCommand("poetry config virtualenvs.in-project true"),
|
||||
plan.NewCopyCommand("pyproject.toml"),
|
||||
plan.NewCopyCommand("poetry.lock"),
|
||||
plan.NewExecCommand("poetry install --no-interaction --no-ansi --only main --no-root"),
|
||||
plan.NewCopyCommand("."),
|
||||
plan.NewPathCommand(VENV_PATH + "/bin"),
|
||||
})
|
||||
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddInput(plan.NewStepInput(install.Name()))
|
||||
|
||||
ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
|
||||
maps.Copy(ctx.Deploy.Variables, p.GetPythonEnvVars(ctx))
|
||||
maps.Copy(ctx.Deploy.Variables, map[string]string{
|
||||
"VIRTUAL_ENV": VENV_PATH,
|
||||
})
|
||||
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(p.GetImageWithRuntimeDeps(ctx).Name()),
|
||||
plan.NewStepInput(ctx.GetMiseStepBuilder().Name(), plan.InputOptions{
|
||||
Include: ctx.GetMiseStepBuilder().GetOutputPaths(),
|
||||
}),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PythonProvider) PlanPip(ctx *generate.GenerateContext) {
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.AddInput(plan.NewStepInput(p.GetBuilderDeps(ctx).Name()))
|
||||
|
||||
install.AddCache(ctx.Caches.AddCache("pip", PIP_CACHE_DIR))
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewCopyCommand("requirements.txt"),
|
||||
plan.NewExecCommand(fmt.Sprintf("pip install --target=%s -r requirements.txt", PACKAGES_DIR)),
|
||||
})
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"PYTHON", "PIP", "PIPX"})
|
||||
maps.Copy(install.Variables, p.GetPythonEnvVars(ctx))
|
||||
maps.Copy(install.Variables, map[string]string{
|
||||
"PIP_CACHE_DIR": PIP_CACHE_DIR,
|
||||
"PYTHONPATH": PACKAGES_DIR,
|
||||
})
|
||||
|
||||
build := ctx.NewCommandStep("build")
|
||||
build.AddInput(plan.NewStepInput(install.Name()))
|
||||
|
||||
ctx.Deploy.StartCmd = p.GetStartCommand(ctx)
|
||||
maps.Copy(ctx.Deploy.Variables, p.GetPythonEnvVars(ctx))
|
||||
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
plan.NewStepInput(p.GetImageWithRuntimeDeps(ctx).Name()),
|
||||
plan.NewStepInput(ctx.GetMiseStepBuilder().Name(), plan.InputOptions{
|
||||
Include: ctx.GetMiseStepBuilder().GetOutputPaths(),
|
||||
}),
|
||||
plan.NewStepInput(build.Name(), plan.InputOptions{
|
||||
Include: []string{PACKAGES_DIR, "."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PythonProvider) GetImageWithRuntimeDeps(ctx *generate.GenerateContext) *generate.AptStepBuilder {
|
||||
aptStep := ctx.NewAptStepBuilder("python-runtime-deps")
|
||||
aptStep.Inputs = []plan.Input{
|
||||
ctx.DefaultRuntimeInput(),
|
||||
}
|
||||
|
||||
for dep, requiredPkgs := range pythonRuntimeDepRequirements {
|
||||
if p.usesDep(ctx, dep) {
|
||||
aptStep.Packages = append(aptStep.Packages, requiredPkgs...)
|
||||
}
|
||||
}
|
||||
|
||||
return aptStep
|
||||
}
|
||||
|
||||
func (p *PythonProvider) GetBuilderDeps(ctx *generate.GenerateContext) *generate.MiseStepBuilder {
|
||||
miseStep := ctx.GetMiseStepBuilder()
|
||||
miseStep.SupportingAptPackages = append(miseStep.SupportingAptPackages, "python3-dev", "libpq-dev")
|
||||
|
||||
return miseStep
|
||||
}
|
||||
|
||||
func (p *PythonProvider) InstallPythonDeps(ctx *generate.GenerateContext, install *generate.CommandStepBuilder) {
|
||||
maps.Copy(install.Variables, p.GetPythonEnvVars(ctx))
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"PYTHON", "PIP", "PIPX", "PIPENV", "UV", "POETRY", "PDM"})
|
||||
install.AddPaths([]string{"/root/.local/bin", "/app/.venv/bin"})
|
||||
|
||||
hasRequirements := p.hasRequirements(ctx)
|
||||
hasPyproject := p.hasPyproject(ctx)
|
||||
@@ -77,13 +336,6 @@ func (p *PythonProvider) install(ctx *generate.GenerateContext) error {
|
||||
hasPdm := p.hasPdm(ctx)
|
||||
hasUv := p.hasUv(ctx)
|
||||
|
||||
setup := ctx.NewCommandStep("setup")
|
||||
setup.AddEnvVars(p.GetPythonEnvVars(ctx))
|
||||
setup.AddPaths([]string{"/root/.local/bin"})
|
||||
|
||||
install := ctx.NewCommandStep("install")
|
||||
install.DependsOn = append(install.DependsOn, setup.DisplayName)
|
||||
|
||||
if hasRequirements {
|
||||
install.AddCache(ctx.Caches.AddCache("pip", PIP_CACHE_DIR))
|
||||
install.AddCommands([]plan.Command{
|
||||
@@ -99,8 +351,6 @@ func (p *PythonProvider) install(ctx *generate.GenerateContext) error {
|
||||
plan.NewExecCommand("poetry install --no-interaction --no-ansi --no-root"),
|
||||
})
|
||||
} else if hasPyproject && hasPdm {
|
||||
// TODO: Fix this. PDM is not working because the packages are installed into a venv
|
||||
// that is not available to python at runtime
|
||||
install.AddEnvVars(map[string]string{"PDM_CHECK_UPDATE": "false"})
|
||||
install.AddCommands([]plan.Command{
|
||||
plan.NewExecCommand("pipx install pdm"),
|
||||
@@ -143,48 +393,39 @@ func (p *PythonProvider) install(ctx *generate.GenerateContext) error {
|
||||
}
|
||||
}
|
||||
|
||||
install.Secrets = []string{}
|
||||
install.UseSecretsWithPrefixes([]string{"PYTHON", "PIP", "PIPX", "PIPENV", "UV", "POETRY", "PDM"})
|
||||
|
||||
// Handle system dependencies
|
||||
aptStep := ctx.NewAptStepBuilder("python-system-deps")
|
||||
aptStep.Packages = []string{"pkg-config"}
|
||||
install.DependsOn = append(install.DependsOn, aptStep.DisplayName)
|
||||
|
||||
for dep, requiredPkgs := range pythonDepRequirements {
|
||||
for dep, requiredPkgs := range pythonRuntimeDepRequirements {
|
||||
if p.usesDep(ctx, dep) {
|
||||
aptStep.Packages = append(aptStep.Packages, requiredPkgs...)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PythonProvider) packages(ctx *generate.GenerateContext) error {
|
||||
packages := ctx.GetMiseStepBuilder()
|
||||
|
||||
python := packages.Default("python", DEFAULT_PYTHON_VERSION)
|
||||
func (p *PythonProvider) InstallMisePackages(ctx *generate.GenerateContext, miseStep *generate.MiseStepBuilder) {
|
||||
python := miseStep.Default("python", DEFAULT_PYTHON_VERSION)
|
||||
|
||||
if envVersion, varName := ctx.Env.GetConfigVariable("PYTHON_VERSION"); envVersion != "" {
|
||||
packages.Version(python, envVersion, varName)
|
||||
miseStep.Version(python, envVersion, varName)
|
||||
}
|
||||
|
||||
if versionFile, err := ctx.App.ReadFile(".python-version"); err == nil {
|
||||
packages.Version(python, string(versionFile), ".python-version")
|
||||
miseStep.Version(python, string(versionFile), ".python-version")
|
||||
}
|
||||
|
||||
if runtimeFile, err := ctx.App.ReadFile("runtime.txt"); err == nil {
|
||||
packages.Version(python, string(runtimeFile), "runtime.txt")
|
||||
miseStep.Version(python, string(runtimeFile), "runtime.txt")
|
||||
}
|
||||
|
||||
if pipfileVersion := parseVersionFromPipfile(ctx); pipfileVersion != "" {
|
||||
packages.Version(python, pipfileVersion, "Pipfile")
|
||||
miseStep.Version(python, pipfileVersion, "Pipfile")
|
||||
}
|
||||
|
||||
if p.hasPoetry(ctx) || p.hasUv(ctx) || p.hasPdm(ctx) {
|
||||
packages.Default("pipx", "latest")
|
||||
if p.hasPoetry(ctx) || p.hasUv(ctx) || p.hasPdm(ctx) || p.hasPipfile(ctx) {
|
||||
miseStep.Default("pipx", "latest")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PythonProvider) GetPythonEnvVars(ctx *generate.GenerateContext) map[string]string {
|
||||
@@ -195,7 +436,6 @@ func (p *PythonProvider) GetPythonEnvVars(ctx *generate.GenerateContext) map[str
|
||||
"PYTHONDONTWRITEBYTECODE": "1",
|
||||
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
|
||||
"PIP_DEFAULT_TIMEOUT": "100",
|
||||
"PIP_CACHE_DIR": PIP_CACHE_DIR,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,15 +454,16 @@ func (p *PythonProvider) addMetadata(ctx *generate.GenerateContext) {
|
||||
pkgManager = "uv"
|
||||
}
|
||||
|
||||
ctx.Metadata.Set("packageManager", pkgManager)
|
||||
ctx.Metadata.SetBool("requirements", p.hasRequirements(ctx))
|
||||
ctx.Metadata.SetBool("pyproject", p.hasPyproject(ctx))
|
||||
ctx.Metadata.SetBool("pipfile", p.hasPipfile(ctx))
|
||||
ctx.Metadata.Set("pythonPackageManager", pkgManager)
|
||||
ctx.Metadata.SetBool("pythonHasRequirementsTxt", p.hasRequirements(ctx))
|
||||
ctx.Metadata.SetBool("pythonHasPyproject", p.hasPyproject(ctx))
|
||||
ctx.Metadata.SetBool("pythonHasPipfile", p.hasPipfile(ctx))
|
||||
}
|
||||
|
||||
func (p *PythonProvider) usesDep(ctx *generate.GenerateContext, dep string) bool {
|
||||
for _, file := range []string{"requirements.txt", "pyproject.toml", "Pipfile"} {
|
||||
if contents, err := ctx.App.ReadFile(file); err == nil {
|
||||
// TODO: Do something better than string comparison
|
||||
if strings.Contains(strings.ToLower(contents), strings.ToLower(dep)) {
|
||||
return true
|
||||
}
|
||||
@@ -272,8 +513,8 @@ func (p *PythonProvider) hasUv(ctx *generate.GenerateContext) bool {
|
||||
}
|
||||
|
||||
// Mapping of python dependencies to required apt packages
|
||||
var pythonDepRequirements = map[string][]string{
|
||||
"pdf2image": {"poppler-utils", "gcc"},
|
||||
"pydub": {"ffmpeg", "gcc"},
|
||||
"pymovie": {"ffmpeg", "qt5-qmake", "qtbase5-dev", "qtbase5-dev-tools", "qttools5-dev-tools", "libqt5core5a", "python3-pyqt5", "gcc"},
|
||||
var pythonRuntimeDepRequirements = map[string][]string{
|
||||
"pdf2image": {"poppler-utils"},
|
||||
"pydub": {"ffmpeg"},
|
||||
"pymovie": {"ffmpeg", "qt5-qmake", "qtbase5-dev", "qtbase5-dev-tools", "qttools5-dev-tools", "libqt5core5a", "python3-pyqt5"},
|
||||
}
|
||||
|
||||
@@ -22,19 +22,27 @@ type StaticfileConfig struct {
|
||||
RootDir string `yaml:"root"`
|
||||
}
|
||||
|
||||
type StaticfileProvider struct{}
|
||||
type StaticfileProvider struct {
|
||||
RootDir string
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) Name() string {
|
||||
return "staticfile"
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) Initialize(ctx *generate.GenerateContext) error {
|
||||
rootDir, err := getRootDir(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.RootDir = rootDir
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) Detect(ctx *generate.GenerateContext) (bool, error) {
|
||||
rootDir, err := p.getRootDir(ctx)
|
||||
|
||||
rootDir, err := getRootDir(ctx)
|
||||
if rootDir != "" && err == nil {
|
||||
return true, nil
|
||||
}
|
||||
@@ -43,90 +51,56 @@ func (p *StaticfileProvider) Detect(ctx *generate.GenerateContext) (bool, error)
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) Plan(ctx *generate.GenerateContext) error {
|
||||
p.Packages(ctx)
|
||||
miseStep := ctx.GetMiseStepBuilder()
|
||||
miseStep.Default("caddy", "latest")
|
||||
|
||||
rootDir, err := p.getRootDir(ctx)
|
||||
setup := ctx.NewCommandStep("setup")
|
||||
setup.AddInput(plan.NewStepInput(miseStep.Name()))
|
||||
err := p.Setup(ctx, setup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
setupStep, err := p.SetupCaddy(ctx, rootDir)
|
||||
if err != nil {
|
||||
return err
|
||||
ctx.Deploy.Inputs = []plan.Input{
|
||||
ctx.DefaultRuntimeInput(),
|
||||
plan.NewStepInput(miseStep.Name(), plan.InputOptions{
|
||||
Include: miseStep.GetOutputPaths(),
|
||||
}),
|
||||
plan.NewStepInput(setup.Name(), plan.InputOptions{
|
||||
Include: []string{"."},
|
||||
}),
|
||||
plan.NewLocalInput("."),
|
||||
}
|
||||
|
||||
setupStep.DependsOn = append(setupStep.DependsOn, ctx.GetMiseStepBuilder().DisplayName)
|
||||
|
||||
ctx.Start.AddOutputs([]string{"."})
|
||||
ctx.Start.Command = p.CaddyStartCommand(ctx, rootDir)
|
||||
ctx.Deploy.StartCmd = p.CaddyStartCommand(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) CaddyStartCommand(ctx *generate.GenerateContext, rootDir string) string {
|
||||
func (p *StaticfileProvider) CaddyStartCommand(ctx *generate.GenerateContext) string {
|
||||
return "caddy run --config " + CaddyfilePath + " --adapter caddyfile 2>&1"
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) SetupCaddy(ctx *generate.GenerateContext, rootDir string) (*generate.CommandStepBuilder, error) {
|
||||
func (p *StaticfileProvider) Setup(ctx *generate.GenerateContext, setup *generate.CommandStepBuilder) error {
|
||||
data := map[string]interface{}{
|
||||
"STATIC_FILE_ROOT": rootDir,
|
||||
"STATIC_FILE_ROOT": p.RootDir,
|
||||
}
|
||||
|
||||
caddyfile, err := p.getCaddyfile(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
setupStep := ctx.NewCommandStep("setup")
|
||||
setupStep.AddCommands([]plan.Command{
|
||||
setup.AddCommands([]plan.Command{
|
||||
plan.NewFileCommand(CaddyfilePath, "Caddyfile"),
|
||||
|
||||
// format to validate the Caddyfile
|
||||
plan.NewExecCommand("caddy fmt --overwrite Caddyfile"),
|
||||
})
|
||||
|
||||
setupStep.Assets = map[string]string{
|
||||
setup.Assets = map[string]string{
|
||||
"Caddyfile": caddyfile,
|
||||
}
|
||||
|
||||
return setupStep, nil
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) Packages(ctx *generate.GenerateContext) {
|
||||
miseStep := ctx.GetMiseStepBuilder()
|
||||
miseStep.Default("caddy", "latest")
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) getRootDir(ctx *generate.GenerateContext) (string, error) {
|
||||
if rootDir, _ := ctx.Env.GetConfigVariable("STATIC_FILE_ROOT"); rootDir != "" {
|
||||
return rootDir, nil
|
||||
}
|
||||
|
||||
staticfileConfig, err := p.getStaticfileConfig(ctx)
|
||||
if staticfileConfig != nil && err == nil {
|
||||
return staticfileConfig.RootDir, nil
|
||||
}
|
||||
|
||||
if ctx.App.HasMatch("public") {
|
||||
return "public", nil
|
||||
} else if ctx.App.HasMatch("index.html") {
|
||||
return ".", nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no static file root dir found")
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) getStaticfileConfig(ctx *generate.GenerateContext) (*StaticfileConfig, error) {
|
||||
if !ctx.App.HasMatch(StaticfileConfigName) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
staticfileData := StaticfileConfig{}
|
||||
if err := ctx.App.ReadYAML(StaticfileConfigName, &staticfileData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &staticfileData, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *StaticfileProvider) getCaddyfile(data map[string]interface{}) (string, error) {
|
||||
@@ -142,3 +116,35 @@ func (p *StaticfileProvider) getCaddyfile(data map[string]interface{}) (string,
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func getRootDir(ctx *generate.GenerateContext) (string, error) {
|
||||
if rootDir, _ := ctx.Env.GetConfigVariable("STATIC_FILE_ROOT"); rootDir != "" {
|
||||
return rootDir, nil
|
||||
}
|
||||
|
||||
staticfileConfig, err := getStaticfileConfig(ctx)
|
||||
if staticfileConfig != nil && err == nil {
|
||||
return staticfileConfig.RootDir, nil
|
||||
}
|
||||
|
||||
if ctx.App.HasMatch("public") {
|
||||
return "public", nil
|
||||
} else if ctx.App.HasMatch("index.html") {
|
||||
return ".", nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no static file root dir found")
|
||||
}
|
||||
|
||||
func getStaticfileConfig(ctx *generate.GenerateContext) (*StaticfileConfig, error) {
|
||||
if !ctx.App.HasMatch(StaticfileConfigName) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
staticfileData := StaticfileConfig{}
|
||||
if err := ctx.App.ReadYAML(StaticfileConfigName, &staticfileData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &staticfileData, nil
|
||||
}
|
||||
|
||||
@@ -88,8 +88,7 @@ func TestGetRootDir(t *testing.T) {
|
||||
ctx.Env.SetVariable(k, v)
|
||||
}
|
||||
|
||||
provider := StaticfileProvider{}
|
||||
got, err := provider.getRootDir(ctx)
|
||||
got, err := getRootDir(ctx)
|
||||
|
||||
if tt.expectError {
|
||||
require.Error(t, err)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/railwayapp/railpack/core/app"
|
||||
"github.com/railwayapp/railpack/core/config"
|
||||
"github.com/railwayapp/railpack/core/generate"
|
||||
)
|
||||
|
||||
@@ -18,7 +19,9 @@ func CreateGenerateContext(t *testing.T, path string) *generate.GenerateContext
|
||||
|
||||
env := app.NewEnvironment(nil)
|
||||
|
||||
ctx, err := generate.NewGenerateContext(userApp, env)
|
||||
config := config.EmptyConfig()
|
||||
|
||||
ctx, err := generate.NewGenerateContext(userApp, env, config)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating generate context: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"$schema": "../../test/schema.json",
|
||||
"providers": ["python"],
|
||||
"provider": "python",
|
||||
"packages": {
|
||||
"python": "latest"
|
||||
},
|
||||
"aptPackages": ["neofetch"],
|
||||
"buildAptPackages": ["neofetch"],
|
||||
"steps": {
|
||||
"build": {
|
||||
"commands": ["neofetch"],
|
||||
@@ -13,7 +13,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "neofetch $HELLO"
|
||||
"deploy": {
|
||||
"aptPackages": ["neofetch"],
|
||||
"startCommand": "neofetch $HELLO"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{
|
||||
"$schema": "../../test/schema.json",
|
||||
"providers": [],
|
||||
"aptPackages": ["cowsay"],
|
||||
"buildAptPackages": ["cowsay"],
|
||||
"steps": {
|
||||
"build": {
|
||||
"commands": [{ "path": "/usr/games" }, "cowsay hello"]
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"cmd": "cowsay hello"
|
||||
"deploy": {
|
||||
"aptPackages": ["cowsay"],
|
||||
"paths": ["/usr/games"],
|
||||
"startCommand": "cowsay hello"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "../../test/schema.json",
|
||||
"packages": {
|
||||
"go": "1.23.5"
|
||||
}
|
||||
}
|
||||
Generated
+22
-2
@@ -1,15 +1,21 @@
|
||||
{
|
||||
"name": "22",
|
||||
"name": "node-npm",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "22",
|
||||
"name": "node-npm",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"dayjs": "^1.11.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "23.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
@@ -17,6 +23,20 @@
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
||||
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
||||
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,5 +15,8 @@
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"dayjs": "^1.11.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import strawberry
|
||||
import numpy as np
|
||||
|
||||
print(np.__version__)
|
||||
print(strawberry)
|
||||
print("Hello from Python-PDM")
|
||||
|
||||
Generated
+59
-34
@@ -3,37 +3,73 @@
|
||||
|
||||
[metadata]
|
||||
groups = ["default"]
|
||||
strategy = ["cross_platform"]
|
||||
strategy = []
|
||||
lock_version = "4.5.0"
|
||||
content_hash = "sha256:05981b9e064b616cee0146951466f6a19becc0b90d22d565d98088945e24e87b"
|
||||
content_hash = "sha256:d74fecdd5593d25e82dc4a1d29e5b2f14bc4bfc9c18873b5db3dc6b655fa1622"
|
||||
|
||||
[[metadata.targets]]
|
||||
requires_python = ">=3.8"
|
||||
|
||||
[[package]]
|
||||
name = "astunparse"
|
||||
version = "1.6.3"
|
||||
summary = "An AST unparser for Python"
|
||||
dependencies = [
|
||||
"six<2.0,>=1.6.1",
|
||||
"wheel<1.0,>=0.23.0",
|
||||
]
|
||||
files = [
|
||||
{file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"},
|
||||
{file = "astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872"},
|
||||
]
|
||||
requires_python = ">=3.11"
|
||||
|
||||
[[package]]
|
||||
name = "graphql-core"
|
||||
version = "3.2.5"
|
||||
version = "3.2.6"
|
||||
requires_python = "<4,>=3.6"
|
||||
summary = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL."
|
||||
dependencies = [
|
||||
"typing-extensions<5,>=4; python_version < \"3.10\"",
|
||||
]
|
||||
files = [
|
||||
{file = "graphql_core-3.2.5-py3-none-any.whl", hash = "sha256:2f150d5096448aa4f8ab26268567bbfeef823769893b39c1a2e1409590939c8a"},
|
||||
{file = "graphql_core-3.2.5.tar.gz", hash = "sha256:e671b90ed653c808715645e3998b7ab67d382d55467b7e2978549111bbabf8d5"},
|
||||
{file = "graphql_core-3.2.6-py3-none-any.whl", hash = "sha256:78b016718c161a6fb20a7d97bbf107f331cd1afe53e45566c59f776ed7f0b45f"},
|
||||
{file = "graphql_core-3.2.6.tar.gz", hash = "sha256:c08eec22f9e40f0bd61d805907e3b3b1b9a320bc606e23dc145eebca07c8fbab"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.2.3"
|
||||
requires_python = ">=3.10"
|
||||
summary = "Fundamental package for array computing in Python"
|
||||
files = [
|
||||
{file = "numpy-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:16372619ee728ed67a2a606a614f56d3eabc5b86f8b615c79d01957062826ca8"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5521a06a3148686d9269c53b09f7d399a5725c47bbb5b35747e1cb76326b714b"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:7c8dde0ca2f77828815fd1aedfdf52e59071a5bae30dac3b4da2a335c672149a"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:77974aba6c1bc26e3c205c2214f0d5b4305bdc719268b93e768ddb17e3fdd636"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d42f9c36d06440e34226e8bd65ff065ca0963aeecada587b937011efa02cdc9d"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2712c5179f40af9ddc8f6727f2bd910ea0eb50206daea75f58ddd9fa3f715bb"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c8b0451d2ec95010d1db8ca733afc41f659f425b7f608af569711097fd6014e2"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9b4a8148c57ecac25a16b0e11798cbe88edf5237b0df99973687dd866f05e1b"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-win32.whl", hash = "sha256:1f45315b2dc58d8a3e7754fe4e38b6fce132dab284a92851e41b2b344f6441c5"},
|
||||
{file = "numpy-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f48ba6f6c13e5e49f3d3efb1b51c8193215c42ac82610a04624906a9270be6f"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:87eed225fd415bbae787f93a457af7f5990b92a334e346f72070bf569b9c9c95"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:712a64103d97c404e87d4d7c47fb0c7ff9acccc625ca2002848e0d53288b90ea"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a5ae282abe60a2db0fd407072aff4599c279bcd6e9a2475500fc35b00a57c532"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5266de33d4c3420973cf9ae3b98b54a2a6d53a559310e3236c4b2b06b9c07d4e"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:34c1b7e83f94f3b564b35f480f5652a47007dd91f7c839f404d03279cc8dd021"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4d8335b5f1b6e2bce120d55fb17064b0262ff29b459e8493d1785c18ae2553b8"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-win32.whl", hash = "sha256:4d9828d25fb246bedd31e04c9e75714a4087211ac348cb39c8c5f99dbb6683fe"},
|
||||
{file = "numpy-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:83807d445817326b4bcdaaaf8e8e9f1753da04341eceec705c001ff342002e5d"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:23c9f4edbf4c065fddb10a4f6e8b6a244342d95966a48820c614891e5059bb50"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:a0c03b6be48aaf92525cccf393265e02773be8fd9551a2f9adbe7db1fa2b60f1"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:2376e317111daa0a6739e50f7ee2a6353f768489102308b0d98fcf4a04f7f3b5"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fb62fe3d206d72fe1cfe31c4a1106ad2b136fcc1606093aeab314f02930fdf2"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1b416af7d0ed3271cad0f0a0d0bee0911ed7eba23e66f8424d9f3dfcdcae1304"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1402da8e0f435991983d0a9708b779f95a8c98c6b18a171b9f1be09005e64d9d"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-win32.whl", hash = "sha256:136553f123ee2951bfcfbc264acd34a2fc2f29d7cdf610ce7daf672b6fbaa693"},
|
||||
{file = "numpy-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:435e7a933b9fda8126130b046975a968cc2d833b505475e588339e09f7672890"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7678556eeb0152cbd1522b684dcd215250885993dd00adb93679ec3c0e6e091c"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2e8da03bd561504d9b20e7a12340870dfc206c64ea59b4cfee9fceb95070ee94"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:c9aa4496fd0e17e3843399f533d62857cef5900facf93e735ef65aa4bbc90ef0"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4ca91d61a4bf61b0f2228f24bbfa6a9facd5f8af03759fe2a655c50ae2c6610"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deaa09cd492e24fd9b15296844c0ad1b3c976da7907e1c1ed3a0ad21dded6f76"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:246535e2f7496b7ac85deffe932896a3577be7af8fb7eebe7146444680297e9a"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:daf43a3d1ea699402c5a850e5313680ac355b4adc9770cd5cfc2940e7861f1bf"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-win32.whl", hash = "sha256:cf802eef1f0134afb81fef94020351be4fe1d6681aadf9c5e862af6602af64ef"},
|
||||
{file = "numpy-2.2.3-cp313-cp313t-win_amd64.whl", hash = "sha256:aee2512827ceb6d7f517c8b85aa5d3923afe8fc7a57d028cffcd522f1c6fd082"},
|
||||
{file = "numpy-2.2.3.tar.gz", hash = "sha256:dbdc15f0c81611925f382dfa97b3bd0bc2c1ce19d4fe50482cb0ddc12ba30020"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -61,18 +97,17 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "strawberry-graphql"
|
||||
version = "0.255.0"
|
||||
requires_python = "<4.0,>=3.8"
|
||||
version = "0.260.2"
|
||||
requires_python = "<4.0,>=3.9"
|
||||
summary = "A library for creating GraphQL APIs"
|
||||
dependencies = [
|
||||
"astunparse<2.0.0,>=1.6.3; python_version < \"3.9\"",
|
||||
"graphql-core<3.4.0,>=3.2.0",
|
||||
"python-dateutil<3.0.0,>=2.7.0",
|
||||
"typing-extensions>=4.5.0",
|
||||
]
|
||||
files = [
|
||||
{file = "strawberry_graphql-0.255.0-py3-none-any.whl", hash = "sha256:890b454cd6ae56e5e63c2a80e1930bd1bd97dcebc91047d89913c2b008110b9f"},
|
||||
{file = "strawberry_graphql-0.255.0.tar.gz", hash = "sha256:bbed6da18887d63d8306b4085cc56370a04e8b15eda87e954e0133674ea824a6"},
|
||||
{file = "strawberry_graphql-0.260.2-py3-none-any.whl", hash = "sha256:b3eb30bb1318b3a2d4405c100618b36e082899309fea8550029ef530d56c1276"},
|
||||
{file = "strawberry_graphql-0.260.2.tar.gz", hash = "sha256:c630a570c941a0c6b34398c7f9c87bcb5af18383557f1a1f45ed957a4ec7f4b7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -84,13 +119,3 @@ files = [
|
||||
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wheel"
|
||||
version = "0.45.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A built-package format for Python"
|
||||
files = [
|
||||
{file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"},
|
||||
{file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"},
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[project]
|
||||
dependencies = [
|
||||
"strawberry-graphql>=0.192.0",
|
||||
]
|
||||
requires-python = ">=3.8"
|
||||
name = "python-pdm"
|
||||
version = "0.1.0"
|
||||
dependencies = ["strawberry-graphql>=0.192.0", "numpy>=1.24.4"]
|
||||
requires-python = ">=3.11"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[
|
||||
{
|
||||
"expectedOutput": "Hello from Python-PDM"
|
||||
}
|
||||
]
|
||||
@@ -7,4 +7,4 @@ print("numpy", np.__version__)
|
||||
print("pandas", pd.__version__)
|
||||
print("psycopg2", psycopg2.__version__)
|
||||
|
||||
print("Hello from Python")
|
||||
print("Hello from UV")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[
|
||||
{
|
||||
"expectedOutput": "Hello from Python"
|
||||
"expectedOutput": "Hello from UV"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
cowsay = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.13"
|
||||
python_full_version = "3.13.2"
|
||||
Generated
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "f855c7f410b3ae66d683bbb0c5940c1f456eabd69a517647f5b4a63804baa5e3"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_full_version": "3.13.2",
|
||||
"python_version": "3.13"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"cowsay": {
|
||||
"hashes": [
|
||||
"sha256:274b1e6fc1b966d53976333eb90ac94cb07a450a700b455af9fbdf882244b30a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==6.1"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import cowsay
|
||||
|
||||
cowsay.cow("Hello from Python-Pipfile")
|
||||
@@ -0,0 +1,5 @@
|
||||
[
|
||||
{
|
||||
"expectedOutput": "Hello from Python-Pipfile"
|
||||
}
|
||||
]
|
||||
@@ -9,26 +9,23 @@
|
||||
"secrets": ["MY_SECRET", "MY_OTHER_SECRET"],
|
||||
"variables": {
|
||||
"NOT_SECRET": "not secret"
|
||||
},
|
||||
"outputs": ["/app"]
|
||||
}
|
||||
},
|
||||
|
||||
"defaultsToUsing": {
|
||||
"commands": [{ "src": ".", "dest": "." }, "./run.sh"],
|
||||
"variables": {
|
||||
"NOT_SECRET": "not secret"
|
||||
},
|
||||
"outputs": ["/app"]
|
||||
}
|
||||
},
|
||||
|
||||
"doesNotUseSecrets": {
|
||||
"commands": [{ "src": ".", "dest": "." }, "./run.sh true"],
|
||||
"secrets": [],
|
||||
"outputs": ["/app"]
|
||||
"secrets": []
|
||||
}
|
||||
},
|
||||
|
||||
"start": {
|
||||
"cmd": "./run.sh"
|
||||
"deploy": {
|
||||
"startCommand": "./run.sh"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[
|
||||
{
|
||||
"expectedOutput": "using config from file"
|
||||
}
|
||||
]
|
||||
@@ -37,6 +37,7 @@ ENV MISE_INSTALL_PATH=/usr/local/bin/mise \
|
||||
MISE_DATA_DIR=/mise \
|
||||
MISE_CONFIG_DIR=/mise \
|
||||
MISE_CACHE_DIR=/mise/cache \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
PATH=/mise/shims:$PATH
|
||||
|
||||
# Copy mise binary from builder
|
||||
|
||||
Reference in New Issue
Block a user