-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add dev server (AKA LaunchDevly) #364
Changes from all commits
0df8497
49013db
0c2dc43
1f199e6
41d748f
29e82af
6bdd657
e510284
c306338
90c2cc4
ba9fdc9
1cf389f
cb04568
42c04b9
fee4159
9a4d7e9
58e9e94
1e4401a
90d4f8b
ae5c240
93d76a1
b1767b7
0747c2b
041e2da
8c4444c
4408830
b6b5535
c06f381
72edc87
e724f8e
9ca5a27
378cd25
9e66b53
a555de4
3f3534e
67b6c5e
f818142
44f410c
cf687ca
314de9f
7273f8d
2848179
d8ac832
8788bbf
d81e962
3ac3aa0
9a515f5
e2cb811
4e0cdba
99c82f5
0eb9b4f
93c4c6f
46eeab0
6f7fbca
cf8efb9
796c61a
27222c0
ddf4190
1a67530
37dddb6
7c6597e
786c548
6192201
7972744
0094020
9aaa95a
c724bc6
002f4d0
ce30082
182028f
dcb35fd
0835398
c045326
426c9f1
3520ec0
a697c08
7e2403c
6f44423
b316f34
1cb8744
e4a353c
3f1f0aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ inputs: | |
tag: | ||
description: 'Tag to upload artifacts to.' | ||
required: true | ||
|
||
outputs: | ||
hashes: | ||
description: sha256sum hashes of built artifacts | ||
|
@@ -29,17 +30,45 @@ runs: | |
with: | ||
platforms: linux/amd64,linux/arm64/v8,linux/arm/v7,linux/386 | ||
- name: Login to Docker | ||
shell: bash | ||
run: echo $DOCKER_TOKEN | docker login --username $DOCKER_USERNAME --password-stdin | ||
|
||
- name: Set up goreleaser | ||
# Note: that we're unable to use the normal goreleaser actions and have to use this docker image. | ||
# This is because the dev server piece of the CLI uses SQLite which requires CGO and cross compilation. | ||
# We're using the goreleaser-cross image to facilitate this. See also: https://github.com/goreleaser/goreleaser-cross | ||
shell: bash | ||
run: | | ||
echo $DOCKER_TOKEN | docker login --username $DOCKER_USERNAME --password-stdin | ||
CONTAINER_ID="$( | ||
docker run --detach \ | ||
--volume "$PWD:$PWD" \ | ||
--entrypoint tail \ | ||
ghcr.io/goreleaser/goreleaser-cross:latest \ | ||
-f /dev/null | ||
)" | ||
docker exec --tty "$CONTAINER_ID" dpkg --add-architecture i386 | ||
docker exec --tty "$CONTAINER_ID" apt-get update | ||
docker exec --tty "$CONTAINER_ID" apt-get install --no-install-recommends -y -q crossbuild-essential-i386 | ||
docker exec --tty "$CONTAINER_ID" git config --global --add safe.directory '*' | ||
echo "CONTAINER_ID=$CONTAINER_ID" >> "$GITHUB_ENV" | ||
|
||
- name: Run Goreleaser | ||
uses: goreleaser/goreleaser-action@v5 | ||
with: | ||
version: latest | ||
args: release ${{ inputs.dry-run == 'true' && '--skip=publish' || '' }} --config .goreleaser.yaml | ||
shell: bash | ||
run: docker exec | ||
--env GITHUB_TOKEN | ||
--env HOMEBREW_DEPLOY_KEY | ||
--workdir "$PWD" | ||
--tty | ||
"$CONTAINER_ID" | ||
goreleaser release ${{ inputs.dry-run == 'true' && '--skip=publish' || '' }} --config .goreleaser.yaml | ||
env: | ||
GITHUB_TOKEN: ${{ inputs.token }} | ||
HOMEBREW_DEPLOY_KEY: ${{ inputs.homebrew-gh-secret }} | ||
- name: Upload assets | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Has it been verified that the uploaded results exactly match (or are expected) compared to previous releases, since the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're still using the goreleaser action. We're just also uploading the artifacts that were generated alongside the action run, so that it's easier to test dry runs. |
||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ldcli | ||
path: dist/* | ||
- name: Hash build artifacts for provenance | ||
id: hash | ||
shell: bash | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
dist/ | ||
*.log | ||
node_modules/ | ||
devserver.db |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,12 @@ | ||
version: 2 | ||
|
||
project_name: ldcli | ||
|
||
env: | ||
- GO111MODULE=on # Ensure we aren't using anything in GOPATH when building | ||
- CGO_ENABLED=1 # Needed for SQLite support | ||
- DOCKER_CLI_EXPERIMENTAL=enabled # This is on by default in docker versions >= 20.10 | ||
|
||
builds: | ||
- id: ldcli | ||
binary: ldcli | ||
|
@@ -6,43 +15,68 @@ builds: | |
- linux | ||
- windows | ||
goarch: | ||
- 386 | ||
- "386" | ||
- amd64 | ||
- arm64 | ||
ldflags: | ||
- -s # Omit all symbol information to minimize binary size | ||
- -w # Omit DWARF to minimize binary size | ||
- -X 'main.version={{.Version}}' | ||
ignore: | ||
- goos: darwin | ||
goarch: "386" | ||
env: | ||
- CGO_ENABLED=0 | ||
# The below environment variables set up the c compiler toolchain for CGO. | ||
# Templates are used to vary the toolchain based on OS & platform. | ||
- TOOLCHAIN_BASE= | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A comment explaining what this is trying to achieve (and why we need to do it manually) would be great 👍 |
||
{{- if eq .Os "darwin" -}} | ||
o | ||
{{- if eq .Arch "arm64" -}}a{{- end -}} | ||
64-clang | ||
{{- else -}} | ||
{{- if eq .Os "windows" -}}/llvm-mingw/bin/{{- end -}} | ||
{{- if eq .Arch "386" -}}i686{{- end -}} | ||
{{- if eq .Arch "arm64" -}}aarch64{{- end -}} | ||
{{- if eq .Arch "amd64" -}}x86_64{{- end -}} | ||
- | ||
{{- if eq .Os "windows" -}}w64-mingw32{{- end -}} | ||
{{- if eq .Os "linux" -}}linux-gnu{{- end -}} | ||
{{- end -}} | ||
- CC={{ .Env.TOOLCHAIN_BASE }}{{ if ne .Os "darwin" }}-gcc{{ end }} | ||
- CXX={{ .Env.TOOLCHAIN_BASE }}{{ if eq .Os "darwin" }}++{{ else }}-g++{{ end }} | ||
|
||
dockers: | ||
# AMD64 | ||
- image_templates: | ||
- "launchdarkly/ldcli:{{ .Version }}-amd64" | ||
- "launchdarkly/ldcli:v{{ .Major }}-amd64" | ||
- "launchdarkly/ldcli:latest-amd64" | ||
- "launchdarkly/ldcli:{{ .Version }}-amd64" | ||
- "launchdarkly/ldcli:v{{ .Major }}-amd64" | ||
- "launchdarkly/ldcli:latest-amd64" | ||
goos: linux | ||
goarch: amd64 | ||
dockerfile: Dockerfile.goreleaser | ||
skip_push: false | ||
build_flag_templates: | ||
- "--pull" | ||
- "--platform=linux/amd64" | ||
- "--pull" | ||
- "--platform=linux/amd64" | ||
|
||
# ARM64v8 | ||
- image_templates: | ||
- "launchdarkly/ldcli:{{ .Version }}-arm64v8" | ||
- "launchdarkly/ldcli:v{{ .Major }}-arm64v8" | ||
- "launchdarkly/ldcli:latest-arm64v8" | ||
- "launchdarkly/ldcli:{{ .Version }}-arm64v8" | ||
- "launchdarkly/ldcli:v{{ .Major }}-arm64v8" | ||
- "launchdarkly/ldcli:latest-arm64v8" | ||
goos: linux | ||
goarch: arm64 | ||
dockerfile: Dockerfile.goreleaser | ||
skip_push: false | ||
build_flag_templates: | ||
- "--pull" | ||
- "--platform=linux/arm64/v8" | ||
- "--pull" | ||
- "--platform=linux/arm64/v8" | ||
docker_manifests: | ||
- name_template: "launchdarkly/ldcli:{{ .Version}}" | ||
skip_push: false | ||
image_templates: | ||
- "launchdarkly/ldcli:{{ .Version }}-amd64" | ||
- "launchdarkly/ldcli:{{ .Version }}-arm64v8" | ||
- "launchdarkly/ldcli:{{ .Version }}-amd64" | ||
- "launchdarkly/ldcli:{{ .Version }}-arm64v8" | ||
|
||
- name_template: "launchdarkly/ldcli:v{{ .Major }}" | ||
skip_push: false | ||
|
@@ -56,8 +90,7 @@ docker_manifests: | |
- "launchdarkly/ldcli:latest-amd64" | ||
- "launchdarkly/ldcli:latest-arm64v8" | ||
brews: | ||
- | ||
name: ldcli | ||
- name: ldcli | ||
description: "The official command line interface for managing LaunchDarkly feature flags." | ||
homepage: "https://launchdarkly.com" | ||
repository: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,44 @@ | ||
package cliflags | ||
|
||
const ( | ||
BaseURIDefault = "https://app.launchdarkly.com" | ||
BaseURIDefault = "https://app.launchdarkly.com" | ||
DevStreamURIDefault = "https://stream.launchdarkly.com" | ||
PortDefault = "8765" | ||
|
||
AccessTokenFlag = "access-token" | ||
AnalyticsOptOut = "analytics-opt-out" | ||
BaseURIFlag = "base-uri" | ||
DataFlag = "data" | ||
EmailsFlag = "emails" | ||
EnvironmentFlag = "environment" | ||
FlagFlag = "flag" | ||
OutputFlag = "output" | ||
ProjectFlag = "project" | ||
RoleFlag = "role" | ||
AccessTokenFlag = "access-token" | ||
AnalyticsOptOut = "analytics-opt-out" | ||
BaseURIFlag = "base-uri" | ||
DataFlag = "data" | ||
DevStreamURIFlag = "dev-stream-uri" | ||
EmailsFlag = "emails" | ||
EnvironmentFlag = "environment" | ||
FlagFlag = "flag" | ||
OutputFlag = "output" | ||
PortFlag = "port" | ||
ProjectFlag = "project" | ||
RoleFlag = "role" | ||
|
||
AccessTokenFlagDescription = "LaunchDarkly access token with write-level access" | ||
AnalyticsOptOutDescription = "Opt out of analytics tracking" | ||
BaseURIFlagDescription = "LaunchDarkly base URI" | ||
DevStreamURIDescription = "Streaming service endpoint that the dev server uses to obtain authoritative flag data. This may be a LaunchDarkly or Relay Proxy endpoint" | ||
EnvironmentFlagDescription = "Default environment key" | ||
FlagFlagDescription = "Default feature flag key" | ||
OutputFlagDescription = "Command response output format in either JSON or plain text" | ||
PortFlagDescription = "Port for the dev server to run on" | ||
ProjectFlagDescription = "Default project key" | ||
) | ||
|
||
func AllFlagsHelp() map[string]string { | ||
return map[string]string{ | ||
AccessTokenFlag: AccessTokenFlagDescription, | ||
AnalyticsOptOut: AnalyticsOptOutDescription, | ||
BaseURIFlag: BaseURIFlagDescription, | ||
EnvironmentFlag: EnvironmentFlagDescription, | ||
FlagFlag: FlagFlagDescription, | ||
OutputFlag: OutputFlagDescription, | ||
ProjectFlag: ProjectFlagDescription, | ||
AccessTokenFlag: AccessTokenFlagDescription, | ||
AnalyticsOptOut: AnalyticsOptOutDescription, | ||
BaseURIFlag: BaseURIFlagDescription, | ||
DevStreamURIFlag: DevStreamURIDescription, | ||
EnvironmentFlag: EnvironmentFlagDescription, | ||
FlagFlag: FlagFlagDescription, | ||
OutputFlag: OutputFlagDescription, | ||
PortFlag: PortFlagDescription, | ||
ProjectFlag: ProjectFlagDescription, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package dev_server | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
|
||
"github.com/launchdarkly/ldcli/cmd/cliflags" | ||
resourcecmd "github.com/launchdarkly/ldcli/cmd/resources" | ||
"github.com/launchdarkly/ldcli/internal/dev_server" | ||
"github.com/launchdarkly/ldcli/internal/resources" | ||
) | ||
|
||
func NewDevServerCmd(client resources.Client, ldClient dev_server.Client) *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "dev-server", | ||
Short: "Development server", | ||
Long: "Start and use a local development server for overriding flag values.", | ||
} | ||
|
||
cmd.PersistentFlags().String( | ||
cliflags.DevStreamURIFlag, | ||
cliflags.DevStreamURIDefault, | ||
cliflags.DevStreamURIDescription, | ||
) | ||
_ = viper.BindPFlag(cliflags.DevStreamURIFlag, cmd.PersistentFlags().Lookup(cliflags.DevStreamURIFlag)) | ||
|
||
cmd.PersistentFlags().String( | ||
cliflags.PortFlag, | ||
cliflags.PortDefault, | ||
cliflags.PortFlagDescription, | ||
) | ||
|
||
_ = viper.BindPFlag(cliflags.PortFlag, cmd.PersistentFlags().Lookup(cliflags.PortFlag)) | ||
|
||
// Add subcommands here | ||
cmd.AddGroup(&cobra.Group{ID: "projects", Title: "Project commands:"}) | ||
cmd.AddCommand(NewListProjectsCmd(client)) | ||
cmd.AddCommand(NewGetProjectCmd(client)) | ||
cmd.AddCommand(NewSyncProjectCmd(client)) | ||
cmd.AddCommand(NewRemoveProjectCmd(client)) | ||
cmd.AddCommand(NewAddProjectCmd(client)) | ||
|
||
cmd.AddGroup(&cobra.Group{ID: "overrides", Title: "Override commands:"}) | ||
cmd.AddCommand(NewAddOverrideCmd(client)) | ||
cmd.AddCommand(NewRemoveOverrideCmd(client)) | ||
cmd.AddGroup(&cobra.Group{ID: "server", Title: "Server commands:"}) | ||
|
||
cmd.AddCommand(NewStartServerCmd(ldClient)) | ||
cmd.AddCommand(NewUICmd()) | ||
|
||
cmd.SetUsageTemplate(resourcecmd.SubcommandUsageTemplate()) | ||
|
||
return cmd | ||
} | ||
|
||
func getDevServerUrl() string { | ||
return fmt.Sprintf("http://localhost:%s", viper.GetString(cliflags.PortFlag)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment explaining why the normal goreleaser-action can't be used would be great