feat: add environment support
Add support for deploying to different environments.
This commit is contained in:
parent
f8c43f9709
commit
a51db2d523
9 changed files with 63 additions and 50 deletions
2
config
2
config
|
@ -1 +1 @@
|
||||||
Subproject commit 40b13ab1b1b52d617851f56d89c4017e0360c3b3
|
Subproject commit 4d9d8e21385c3c9fe481930ab157724f8d5d0dcc
|
|
@ -6,13 +6,13 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
RootDomain string `json:"rootDomain"`
|
RootDomain string `json:"rootDomain"`
|
||||||
FlowGID int32 `json:"flowGID"`
|
FlowGID int32 `json:"flowGID"`
|
||||||
DockerNetworkSubnet string `json:"dockerNetworkSubnet"`
|
Docker dockerConfig `json:"docker"`
|
||||||
DockerHost string `json:"dockerHost"`
|
|
||||||
Traefik traefikConfig `json:"traefik"`
|
Traefik traefikConfig `json:"traefik"`
|
||||||
Forgejo forgejoConfig `json:"forgejo"`
|
Forgejo forgejoConfig `json:"forgejo"`
|
||||||
GoToSocial gotosocialConfig `json:"gotosocial"`
|
GoToSocial gotosocialConfig `json:"gotosocial"`
|
||||||
|
@ -20,6 +20,16 @@ type config struct {
|
||||||
Landing landingConfig `json:"landing"`
|
Landing landingConfig `json:"landing"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dockerConfig struct {
|
||||||
|
Host string `json:"host"`
|
||||||
|
Network dockerNetworkConfig `json:"network"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type dockerNetworkConfig struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Subnet string `json:"subnet"`
|
||||||
|
}
|
||||||
|
|
||||||
type traefikConfig struct {
|
type traefikConfig struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
CheckNewVersion bool `json:"checkNewVersion"`
|
CheckNewVersion bool `json:"checkNewVersion"`
|
||||||
|
@ -108,14 +118,16 @@ type landingConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type landingConfigLinks struct {
|
type landingConfigLinks struct {
|
||||||
Title string
|
Title string `json:"title"`
|
||||||
URL string
|
URL string `json:"url"`
|
||||||
Rel string
|
Rel string `json:"rel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConfig(path string) (config, error) {
|
func newConfig(environment string) (config, error) {
|
||||||
var c config
|
var c config
|
||||||
|
|
||||||
|
path := filepath.Join(configDir, environment, configFileName)
|
||||||
|
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c, fmt.Errorf("unable to open the file; %w", err)
|
return c, fmt.Errorf("unable to open the file; %w", err)
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
const (
|
const (
|
||||||
configFile string = "./config/services.json"
|
configDir string = "./config/"
|
||||||
|
configFileName string = "services.json"
|
||||||
rootBuildDir string = "./build"
|
rootBuildDir string = "./build"
|
||||||
templateExtension string = ".gotmpl"
|
templateExtension string = ".gotmpl"
|
||||||
rootTemplatesDir string = "./templates"
|
rootTemplatesDir string = "./templates"
|
||||||
|
|
|
@ -11,25 +11,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deploy deploys the services to the Flow Platform.
|
// Deploy deploys the services to the Flow Platform.
|
||||||
func Deploy(name string) error {
|
func Deploy(environment, name string) error {
|
||||||
os.Setenv("MAGEFILE_VERBOSE", "true")
|
os.Setenv("MAGEFILE_VERBOSE", "true")
|
||||||
|
|
||||||
mg.Deps(
|
mg.Deps(
|
||||||
mg.F(Prepare, name),
|
mg.F(Prepare, name),
|
||||||
)
|
)
|
||||||
|
|
||||||
cfg, err := newConfig(configFile)
|
cfg, err := newConfig(environment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load the configuration; %w", err)
|
return fmt.Errorf("unable to load the configuration; %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Setenv("DOCKER_HOST", cfg.DockerHost)
|
os.Setenv("DOCKER_HOST", cfg.Docker.Host)
|
||||||
|
|
||||||
command := []string{
|
command := []string{
|
||||||
"docker",
|
"docker",
|
||||||
"compose",
|
"compose",
|
||||||
"--project-directory",
|
"--project-directory",
|
||||||
rootBuildDir+"/compose",
|
fmt.Sprintf("%s/%s/compose", rootBuildDir, environment),
|
||||||
"up",
|
"up",
|
||||||
"-d",
|
"-d",
|
||||||
"--build",
|
"--build",
|
||||||
|
|
|
@ -14,23 +14,23 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Download downloads the binaries for a given service.
|
// Download downloads the binaries for a given service.
|
||||||
func Download(name string) error {
|
func Download(environment, name string) error {
|
||||||
cfg, err := newConfig(configFile)
|
cfg, err := newConfig(environment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load the configuration; %v", err)
|
return fmt.Errorf("unable to load the configuration; %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch name {
|
switch name {
|
||||||
case "forgejo":
|
case "forgejo":
|
||||||
if err := downloadForgejo(cfg.Forgejo.Version); err != nil {
|
if err := downloadForgejo(environment, cfg.Forgejo.Version); err != nil {
|
||||||
return fmt.Errorf("an error occurred whilst getting the forgejo binary; %w", err)
|
return fmt.Errorf("an error occurred whilst getting the forgejo binary; %w", err)
|
||||||
}
|
}
|
||||||
case "gotosocial":
|
case "gotosocial":
|
||||||
if err := downloadGoToSocial(cfg.GoToSocial.Version); err != nil {
|
if err := downloadGoToSocial(environment, cfg.GoToSocial.Version); err != nil {
|
||||||
return fmt.Errorf("an error occurred whilst getting the packages for GoToSocial; %w", err)
|
return fmt.Errorf("an error occurred whilst getting the packages for GoToSocial; %w", err)
|
||||||
}
|
}
|
||||||
case "woodpecker":
|
case "woodpecker":
|
||||||
if err := downloadWoodpecker(cfg.Woodpecker.Version); err != nil {
|
if err := downloadWoodpecker(environment, cfg.Woodpecker.Version); err != nil {
|
||||||
return fmt.Errorf("an error occurred whilst getting the packages for Woodpecker; %w", err)
|
return fmt.Errorf("an error occurred whilst getting the packages for Woodpecker; %w", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -41,8 +41,8 @@ func Download(name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// downloadWoodpecker downloads and validates the files for the Woodpecker deployment.
|
// downloadWoodpecker downloads and validates the files for the Woodpecker deployment.
|
||||||
func downloadWoodpecker(version string) error {
|
func downloadWoodpecker(environment, version string) error {
|
||||||
destinationDir := filepath.Join(rootBuildDir, "woodpecker")
|
destinationDir := filepath.Join(rootBuildDir, environment, "woodpecker")
|
||||||
|
|
||||||
binaryTarUrl := fmt.Sprintf(
|
binaryTarUrl := fmt.Sprintf(
|
||||||
"https://github.com/woodpecker-ci/woodpecker/releases/download/v%s/woodpecker-server_linux_amd64.tar.gz",
|
"https://github.com/woodpecker-ci/woodpecker/releases/download/v%s/woodpecker-server_linux_amd64.tar.gz",
|
||||||
|
@ -69,14 +69,14 @@ func downloadWoodpecker(version string) error {
|
||||||
packages: []pack{
|
packages: []pack{
|
||||||
{
|
{
|
||||||
file: object{
|
file: object{
|
||||||
source: binaryTarUrl,
|
source: binaryTarUrl,
|
||||||
destination: binaryTarFilepath,
|
destination: binaryTarFilepath,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validateGPGSignature: false,
|
validateGPGSignature: false,
|
||||||
checksum: object{
|
checksum: object{
|
||||||
source: checksumUrl,
|
source: checksumUrl,
|
||||||
destination: checksumFilePath,
|
destination: checksumFilePath,
|
||||||
},
|
},
|
||||||
validateChecksum: false,
|
validateChecksum: false,
|
||||||
|
@ -90,7 +90,7 @@ func downloadWoodpecker(version string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// downloadForgejo downloads and validates the Forgejo files.
|
// downloadForgejo downloads and validates the Forgejo files.
|
||||||
func downloadForgejo(version string) error {
|
func downloadForgejo(environment, version string) error {
|
||||||
var (
|
var (
|
||||||
forgejoBinaryFileFormat = "forgejo-%s-linux-amd64"
|
forgejoBinaryFileFormat = "forgejo-%s-linux-amd64"
|
||||||
forgejoDigestExtension = ".sha256"
|
forgejoDigestExtension = ".sha256"
|
||||||
|
@ -98,7 +98,7 @@ func downloadForgejo(version string) error {
|
||||||
forgejoJson = "./magefiles/forgejo.json"
|
forgejoJson = "./magefiles/forgejo.json"
|
||||||
)
|
)
|
||||||
|
|
||||||
destinationDir := filepath.Join(rootBuildDir, "forgejo")
|
destinationDir := filepath.Join(rootBuildDir, environment, "forgejo")
|
||||||
|
|
||||||
binaryPath := filepath.Join(
|
binaryPath := filepath.Join(
|
||||||
destinationDir,
|
destinationDir,
|
||||||
|
@ -144,8 +144,8 @@ func downloadForgejo(version string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// downloadGoToSocial downloads and validates the files for GoToSocial.
|
// downloadGoToSocial downloads and validates the files for GoToSocial.
|
||||||
func downloadGoToSocial(version string) error {
|
func downloadGoToSocial(environment, version string) error {
|
||||||
destinationDir := filepath.Join(rootBuildDir, "gotosocial")
|
destinationDir := filepath.Join(rootBuildDir, environment, "gotosocial")
|
||||||
|
|
||||||
binaryTarUrl := fmt.Sprintf(
|
binaryTarUrl := fmt.Sprintf(
|
||||||
"https://github.com/superseriousbusiness/gotosocial/releases/download/v%s/gotosocial_%s_linux_amd64.tar.gz",
|
"https://github.com/superseriousbusiness/gotosocial/releases/download/v%s/gotosocial_%s_linux_amd64.tar.gz",
|
||||||
|
|
|
@ -16,8 +16,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Prepare prepares the service's build directory.
|
// Prepare prepares the service's build directory.
|
||||||
func Prepare(service string) error {
|
func Prepare(environment, service string) error {
|
||||||
cfg, err := newConfig(configFile)
|
cfg, err := newConfig(environment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load the configuration; %v", err)
|
return fmt.Errorf("unable to load the configuration; %v", err)
|
||||||
}
|
}
|
||||||
|
@ -35,53 +35,53 @@ func Prepare(service string) error {
|
||||||
|
|
||||||
service := o.Name()
|
service := o.Name()
|
||||||
|
|
||||||
buildDir := filepath.Join(rootBuildDir, service)
|
buildDir := filepath.Join(rootBuildDir, environment, service)
|
||||||
|
|
||||||
if _, err := os.Stat(buildDir); err != nil {
|
if _, err := os.Stat(buildDir); err != nil {
|
||||||
if err := os.Mkdir(buildDir, 0o700); err != nil {
|
if err := os.MkdirAll(buildDir, 0o700); err != nil {
|
||||||
return fmt.Errorf("unable to make %s; %w", buildDir, err)
|
return fmt.Errorf("unable to make %s; %w", buildDir, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if service != "compose" {
|
if service != "compose" {
|
||||||
mg.Deps(
|
mg.Deps(
|
||||||
mg.F(Download, service),
|
mg.F(Download, environment, service),
|
||||||
)
|
)
|
||||||
|
|
||||||
log.Printf("Copying assets for %s.\n", service)
|
log.Printf("Copying assets for %s.\n", service)
|
||||||
if err := copyAssets(service); err != nil {
|
if err := copyAssets(environment, service); err != nil {
|
||||||
return fmt.Errorf("unable to copy the assets for %s; %w", service, err)
|
return fmt.Errorf("unable to copy the assets for %s; %w", service, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Rendering templates for %s.\n", service)
|
log.Printf("Rendering templates for %s.\n", service)
|
||||||
if err := render(cfg, service); err != nil {
|
if err := render(cfg, environment, service); err != nil {
|
||||||
return fmt.Errorf("unable to render templates for %s; %w", service, err)
|
return fmt.Errorf("unable to render templates for %s; %w", service, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buildDir := filepath.Join(rootBuildDir, service)
|
buildDir := filepath.Join(rootBuildDir, environment, service)
|
||||||
|
|
||||||
if _, err := os.Stat(buildDir); err != nil {
|
if _, err := os.Stat(buildDir); err != nil {
|
||||||
if err := os.Mkdir(buildDir, 0o700); err != nil {
|
if err := os.MkdirAll(buildDir, 0o700); err != nil {
|
||||||
return fmt.Errorf("unable to make %s; %w", buildDir, err)
|
return fmt.Errorf("unable to make %s; %w", buildDir, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if service != "compose" {
|
if service != "compose" {
|
||||||
mg.Deps(
|
mg.Deps(
|
||||||
mg.F(Download, service),
|
mg.F(Download, environment, service),
|
||||||
mg.F(Prepare, "compose"),
|
mg.F(Prepare, environment, "compose"),
|
||||||
)
|
)
|
||||||
|
|
||||||
log.Printf("Copying assets for %s.\n", service)
|
log.Printf("Copying assets for %s.\n", service)
|
||||||
if err := copyAssets(service); err != nil {
|
if err := copyAssets(environment, service); err != nil {
|
||||||
return fmt.Errorf("unable to copy the assets for %s; %w", service, err)
|
return fmt.Errorf("unable to copy the assets for %s; %w", service, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := render(cfg, service); err != nil {
|
if err := render(cfg, environment, service); err != nil {
|
||||||
return fmt.Errorf("an error occurred whilst rendering the templates; %w", err)
|
return fmt.Errorf("an error occurred whilst rendering the templates; %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ func Prepare(service string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func render(cfg config, component string) error {
|
func render(cfg config, environment, component string) error {
|
||||||
buildDirName := filepath.Join(rootBuildDir, component)
|
buildDirName := filepath.Join(rootBuildDir, environment, component)
|
||||||
|
|
||||||
templateDirName := filepath.Join(rootTemplatesDir, component)
|
templateDirName := filepath.Join(rootTemplatesDir, component)
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ func render(cfg config, component string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyAssets(service string) error {
|
func copyAssets(environment, service string) error {
|
||||||
assetsDirName := filepath.Join(rootAssetsDir, service)
|
assetsDirName := filepath.Join(rootAssetsDir, service)
|
||||||
if _, err := os.Stat(assetsDirName); err != nil {
|
if _, err := os.Stat(assetsDirName); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -158,7 +158,7 @@ func copyAssets(service string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
buildDirName := filepath.Join(rootBuildDir, service, "assets")
|
buildDirName := filepath.Join(rootBuildDir, environment, service, "assets")
|
||||||
|
|
||||||
walkDirFunc := func(path string, d fs.DirEntry, err error) error {
|
walkDirFunc := func(path string, d fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -13,11 +13,11 @@ version: "3.9"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
flow:
|
flow:
|
||||||
name: "flow"
|
name: "{{ .Docker.Network.Name }}"
|
||||||
ipam:
|
ipam:
|
||||||
driver: "default"
|
driver: "default"
|
||||||
config:
|
config:
|
||||||
- subnet: "{{ .DockerNetworkSubnet }}"
|
- subnet: "{{ .Docker.Network.Subnet }}"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# -- Traffic flow --
|
# -- Traffic flow --
|
||||||
|
@ -27,7 +27,7 @@ services:
|
||||||
build:
|
build:
|
||||||
context: "../traefik"
|
context: "../traefik"
|
||||||
networks:
|
networks:
|
||||||
flow:
|
{{ .Docker.Network.Name }}:
|
||||||
ipv4_address: "{{ .Traefik.ContainerIpv4Address }}"
|
ipv4_address: "{{ .Traefik.ContainerIpv4Address }}"
|
||||||
ports:
|
ports:
|
||||||
- target: 80
|
- target: 80
|
||||||
|
@ -59,7 +59,7 @@ services:
|
||||||
- "{{ .Forgejo.SshPort }}"
|
- "{{ .Forgejo.SshPort }}"
|
||||||
- "{{ .Forgejo.HttpPort }}"
|
- "{{ .Forgejo.HttpPort }}"
|
||||||
networks:
|
networks:
|
||||||
flow:
|
{{ .Docker.Network.Name }}:
|
||||||
ipv4_address: "{{ .Forgejo.ContainerIpv4Address }}"
|
ipv4_address: "{{ .Forgejo.ContainerIpv4Address }}"
|
||||||
restart: "always"
|
restart: "always"
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -79,7 +79,7 @@ services:
|
||||||
expose:
|
expose:
|
||||||
- "{{ .GoToSocial.Port }}"
|
- "{{ .GoToSocial.Port }}"
|
||||||
networks:
|
networks:
|
||||||
flow:
|
{{ .Docker.Network.Name }}:
|
||||||
ipv4_address: "{{ .GoToSocial.ContainerIpv4Address }}"
|
ipv4_address: "{{ .GoToSocial.ContainerIpv4Address }}"
|
||||||
restart: "always"
|
restart: "always"
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -114,7 +114,7 @@ services:
|
||||||
- "{{ .Woodpecker.HttpPort }}"
|
- "{{ .Woodpecker.HttpPort }}"
|
||||||
- "{{ .Woodpecker.GrpcPort }}"
|
- "{{ .Woodpecker.GrpcPort }}"
|
||||||
networks:
|
networks:
|
||||||
flow:
|
{{ .Docker.Network.Name }}:
|
||||||
ipv4_address: "{{ .Woodpecker.ContainerIpv4Address }}"
|
ipv4_address: "{{ .Woodpecker.ContainerIpv4Address }}"
|
||||||
restart: "always"
|
restart: "always"
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -138,7 +138,7 @@ services:
|
||||||
expose:
|
expose:
|
||||||
- "{{ .Landing.Port }}"
|
- "{{ .Landing.Port }}"
|
||||||
networks:
|
networks:
|
||||||
flow:
|
{{ .Docker.Network.Name }}:
|
||||||
ipv4_address: "{{ .Landing.ContainerIpv4Address }}"
|
ipv4_address: "{{ .Landing.ContainerIpv4Address }}"
|
||||||
restart: "always"
|
restart: "always"
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
@ -110,7 +110,7 @@ port: {{ .GoToSocial.Port }}
|
||||||
# Example: ["127.0.0.1/32", "172.20.0.1"]
|
# Example: ["127.0.0.1/32", "172.20.0.1"]
|
||||||
# Default: ["127.0.0.1/32", "::1"] (localhost ipv4 + ipv6)
|
# Default: ["127.0.0.1/32", "::1"] (localhost ipv4 + ipv6)
|
||||||
trusted-proxies:
|
trusted-proxies:
|
||||||
- "{{ .DockerNetworkSubnet }}"
|
- "{{ .Docker.Network.Subnet }}"
|
||||||
|
|
||||||
############################
|
############################
|
||||||
##### DATABASE CONFIG ######
|
##### DATABASE CONFIG ######
|
||||||
|
|
Loading…
Reference in a new issue