// Package sunrise embeds the SummerCMS bootstrap script, new.sh, so the // script is versioned with the framework release that ships it. // // The script is what `curl -fsSL https://summercms.io/new | bash -s -- ` // runs: it checks for Go 1.27 or newer, git and Docker, clones the framework // at its newest release tag (or moves an existing release checkout forward), // installs the summer CLI and runs `summer new ` next to the checkout. // A web server hands out Script() as text/plain. // // The same script has an update mode, which // `curl -fsSL https://summercms.io/update | bash` runs inside one // application: it moves the framework checkout named by the application's // go.mod forward, reinstalls summer and rebuilds that application. // UpdateScript() is the script with update mode preset, for the /update URL. package sunrise import ( "bytes" _ "embed" ) //go:embed new.sh var script []byte // Script returns the bootstrap script. Each call returns a fresh copy, so a // caller may modify the slice without affecting later calls. func Script() []byte { return bytes.Clone(script) } const ( mainCall = "main \"$@\"\n" updateCall = "main \"$@\" --update\n" ) var updateScript = deriveUpdateScript(script) // deriveUpdateScript replaces the final `main "$@"` line of s with // `main "$@" --update`. It panics when s does not end with that line, so a // changed script fails every test instead of serving create mode at /update. func deriveUpdateScript(s []byte) []byte { if !bytes.HasSuffix(s, []byte(mainCall)) { panic(`sunrise: new.sh must end with the line main "$@"`) } out := bytes.Clone(s[:len(s)-len(mainCall)]) return append(out, updateCall...) } // UpdateScript returns the bootstrap script with update mode preset: Script() // with its final line `main "$@"` replaced by `main "$@" --update`, so both // URLs serve the same logic. The flag follows "$@" so that every proper // prefix of the last line, as a cut-short download delivers it, calls main // without a valid --update or with no arguments, and main exits with the // usage instead of running anything. Each call returns a fresh copy. func UpdateScript() []byte { return bytes.Clone(updateScript) }