Skip to content

Commit

Permalink
fix: Go build/deploy page revamp
Browse files Browse the repository at this point in the history
Same table/headers in env var reference and Go page, but not as a partial, as it will certainly not be necessary anymore in a coming update
  • Loading branch information
davlgd committed Jan 7, 2024
1 parent 90eb393 commit 49824b1
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 142 deletions.
6 changes: 1 addition & 5 deletions content/doc/applications/golang/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ aliases:

## Overview

Clever Cloud allows you to deploy any Go application. This page will explain you how to set up your application to run it on our service.

We currently support single module applications only. That means that your sources files just need to be at the project's root, and you can't have multiple modules running.

You do not need to change a lot in your application, the *requirements* will help you configure your applications with some mandatory files to add, and properties to setup.
Clever Cloud allows you to deploy any Go application. This page will explain you how to set up your project to run it on our service. You won't not need to change a lot, the *requirements* will help you configure your applications with some mandatory files to add, and properties to setup.

{{< readfile file="create-application.md" >}}

Expand Down
10 changes: 5 additions & 5 deletions content/doc/reference/reference-environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,11 @@ If `TAILSCALE_LOGIN_SERVER` is provided, the agent will be configured to reach a

[Go Documentation](/doc/applications/golang)

| Name | Description | Default value |
|-----------------------|------------------------------|--------------------------------|
|`CC_GO_BUILD_TOOL` |Available values: `gomod`, `gobuild`, `goget`. Makes the deployer use `go modules`, `go get` or `go build` to build your application. | `goget` |
|`CC_GO_PKG` | Makes the deployer run go get `${CC_GO_PKG}` instead of go get `<app_id>`. | |
|`CC_GO_RUNDIR` | Makes the deployer use the specified directory to run your binary. If your application must be in `$GOPATH/src/company/project` for your vendored dependencies, set this variable to `company/project` | |
| Name | Descrption |
| :------- | :---- |
| `CC_GO_BUILD_TOOL` | Available values: `gomod`, `gobuild`. Build and install your application. `goget` still exists but is deprecated. |
| `CC_GO_RUNDIR` | Run the application from the specified path, relative to `$GOPATH/src/`, now deprecated. |
| `CC_GO_PKG` | Tell the `CC_GO_BUILD_TOOL` which file contains the `main()` function, default `main.go`. |

## Haskell

Expand Down
219 changes: 87 additions & 132 deletions static/partials/language-specific-deploy/go.md
Original file line number Diff line number Diff line change
@@ -1,137 +1,92 @@
## Configure your Go application

### Mandatory configuration

Be sure that:

* Your application listens to the wild network **0.0.0.0**, not only `localhost` or `127.0.0.1`
* Your application listens on port **8080**
* You put your main code in a file named `main.go` (if you do not do that, Go will generate a library and not an executable)

Apart from listening on port 8080, there is nothing to change on your application.

### Go production build on Clever Cloud

* We automatically build and run your application, see [Build the application](#build-the-application).
* By default, we consider that your repository contains a single application. We put your application in `${GOPATH}/src/{app_id}` and then run `go get {app_id}`. Refer to [clevercloud/go.json settings](#clevercloud/go.json-settings) if you want to override this behaviour.
* By default, we deploy your application as a Go project named "<app_id>". You can find the app_id of your application under the environment variable `APP_ID`. Please refer to [environment injection](#environment-injection) to know how to query it in your application.
* The executable is run with the application's root as its current path. So if your application has a `static` folder at its root, it will be accessible via `./static` in your application.

## Build the application

To build your application, you can use one of the three methods available:

- `go modules`
- `go build`
- `go get` (default)

### Go modules

If your project is compatible with go modules, be sure that the `go.mod` file is in your git tree. Note that it **must** be at the root of your application (see the [`APP_FOLDER` environment variable if it isn't]({{< ref "doc/reference/reference-environment-variables.md" >}})

For now, you have to add the environment variable `CC_GO_BUILD_TOOL=gomod` to build using the go modules. In a future release, we will automatically
build with go modules if the `go.mod` file is present at the root of your git tree.

Your project's entrypoint should be in the same folder as the `go.mod` file and be named `main.go`. If it isn't, you have to specify it using the following environment variable:

`CC_GO_PKG=./path/to/entrypoint.go`

### Go build

If your project does not support `go modules`, it may include your vendored dependencies. In this case, `go build` must be used.

To use `go build`, you have to set the `CC_GO_BUILD_TOOL=gobuild` environment variable.
We will then deploy your project in a classic `GOPATH` hierarchy using `go build`.

The `CC_GO_PKG` environment variable can be used to define the main file of your application. Defaults to `main.go`.

### Go get

* If your application has submodules and imports them with their full path *or* your main project is an external package hosted, for instance on GitHub (like `github.com/me/myproject`), you can [define the environment variable](#setting-up-environment-variables-on-clever-cloud) `CC_GO_PKG=github.com/me/myproject`. We will now run `go get ${CC_GO_PKG}` instead of `go get <app_id>`.

Also, go get requires that you put your main code in a file named `main.go`. If you
do not do that, go will generate a library and not an executable. So if you get a `Nothing
listening on port 8080`, please check that your main file is named `main.go`.

You can also force the use of `go get` by setting the environment variable `CC_GO_BUILD_TOOL=goget`. This is currently the default.

**Note**: if you get a `Nothing listening on port 8080` error, please check that your main file is named `main.go`.

### Customize build using environment variables

### Customize build using environment variables

You can customize the build process of your Go application using the following environment variables:

Variable | Usage
---------|------
`CC_GO_PKG` | Makes the deployer run `go get ${CC_GO_PKG}` instead of `go get <app_id>` or `go install ${CC_GO_PKG}` instead of `go install mypackage`.
`CC_GO_BUILD_TOOL` | Available values: `gomod`, `goget`, `gobuild`. Makes the deployer use `go modules`, `go get`, or `go build` to build your application. If not specified, defaults to `goget`.
`CC_GO_RUNDIR` | Makes the deployer use the specified directory to run your binary. If your application must be in `$GOPATH/src/company/project` for your vendored dependencies, set this variable to `company/project`.

### clevercloud/go.json

This configuration file is optional.

If you want to configure precisely your dependencies (e.g. have private libraries, or specific versions of some libraries), here is the way:

1. Make your repository have a `GOPATH` structure:
```txt
./
src/
myapp/
foo/
module1/
module2/
module3/
```
Here you have the modules `myapp`, `foo/module1`, `foo/module2` and `module3`.
2. Create a *clevercloud/go.json* file at the top of your repository:
```txt
./
clevercloud/
go.json
src/
myapp/
...
```
3. In the go.json file, put the following:
```json
{
"deploy": {
"appIsGoPath": true,
"main": "myapp"
}
}
```
If `appIsGoPath` is present and equals `true`, then we consider that your repo root is the *GOPATH*.
The `main` field then becomes mandatory and must be the name of the module you want to run.
E.g. if you want to run `module1`, `main` must be `foo/module1`.
4. (Optional) Add a "execDir" field to the "deploy" object:
```json
{
"deploy": {
"appIsGoPath": true,
"main": "myapp",
"execDir": "src/myapp"
}
}
```
The `execDir` value must be relative to the root of your repo.
In the example above, we will run the application in the src/myapp directory.
### Mandatory needs
By default, we consider that your repository contains a single application. Be sure that:
* It listens to the wild network `0.0.0.0`, not only `localhost` or `127.0.0.1`
* It listens on port `8080`
* You follow our build/run instructions

In most cases you won't need to change anything to your application, except host/port and some configuration variables.

### Modern Go project structure
There are multiple ways to build/run a Go application, and this has evolved over the years. In its modern form a Go project can be a:
- `Package`: one or more `.go` files you can `build` or `run`. `main` package and `main()` function are the default entry point
- `Module`: one or more packages you can `install`, defined in a `go.mod` file (`go.sum` for checksums)
- `Workspace`: one or more modules seamlessly combined, defined in a `go.work` file

A module can be installed locally or from a remote repository if you pass its URL to the `install` command. A `Makefile` is sometimes used to define how a Go project is built, run and/or cleaned. The lightest form of a Go project is a `main.go` file to build. Some years ago, the `src/` folder was often used for source code, but using the `cmd/` folder instead is now a common practice.

If you want to limit from where a package can be imported it [should placed](https://docs.google.com/document/d/1e8kOo3r51b2BWtTs_1uADIA5djfXhPT36s6eHVRIvaU/edit) in a folder named `ìnternal/`. Access to functions in `.go` files is defined depending [on their name](https://go.dev/tour/basics/3): if it starts with a capital letter it's a public functions, if not it's a private function.

For a complete project, a common files/folders organization can be:
```
application-root/
├── go.work
├── Makefile
├── cmd/
│ ├── main.go
│ ├── other-file.go
│ ├── other-package.go
| └── ...
└── module/
├── go.mod
├── go.sum
├── main.go
├── other-module-file.go
└──internal/
└── internal-package/
└── internal-package-file.go
```

### Go build and deploy on Clever Cloud
In such a situation, our strategy is to let the user choose how to build/run its application and make the deployment easy anyway. At first, we used the `goget` method, which is now deprecated. Thus, you can now use `gobuild` (for packages), `gomod` (for modules) or a configuration file. The latter will allow you to define a `Makefile` for custom build and a `main` executable to start the application.

{{< callout type="info" >}}
If the required Go version declared in the `go.mod` is superior to the version built in the instance, it will be automatically updated.
{{< /callout >}}

#### Through Makefile and JSON configuration
Create a file name `go.json` in a `clevercloud/` folder at the root of your repository. It will allow you to ask for a custom build through a `Makefile` ([learn more about it](https://en.wikipedia.org/wiki/Make_(software)#Makefiles)). For example with a single package in `main.go`:

`/clevercloud/go.json`
```json
{
"deploy": {
"makefile": "Makefile",
"main": "bin/myApp"
}
}
```

`/Makefile`
```Makefile
BINARY=bin/myApp

build:
# To install a specific Go version, you can add:
# go install golang.org/dl/gox.xx.x@latest
# ${HOME}/go_home/bin/gox.xx.x download
# Then use `${HOME}/go_home/bin/gox.xx.x` instead of `go`
echo "Build the application as ./${BINARY}"
go build -o ${BINARY} main.go
```

You'll find a more complex project using a Go Workspace and a `Makefile` [here](https://github.com/CleverCloud/go-workspaces).

#### Through Environment variables
If you don't want to add a file to your project, you can set one of these environment variables:

| Name | Description |
| :------- | :---- |
| `CC_GO_BUILD_TOOL` | Available values: `gomod`, `gobuild`. Build and install your application. `goget` still exists but is deprecated. |
| `CC_GO_RUNDIR` | Run the application from the specified path, relative to `$GOPATH/src/`, now deprecated. |
| `CC_GO_PKG` | Tell the `CC_GO_BUILD_TOOL` which file contains the `main()` function, default `main.go`. |

- **gobuild**
To build a Go package, your project may include vendored dependencies (in the `vendor/` folder). `CC_GO_PKG` can be set to define the main file of your application (default `main.go`).

- **gomod**
To build a Go module, be sure that the `go.mod` file is in your git tree and at the root of your application. Your project's entrypoint should be in the same folder as the `go.mod` file and be named `main.go`. If it isn't, you have to set `CC_GO_PKG=path/to/entrypoint.go`.

{{< readfile file="env-injection.md" >}}

Expand Down

0 comments on commit 49824b1

Please sign in to comment.