Skip to content
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

Merged
merged 82 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
0df8497
Initial API spec
mike-zorn Jun 24, 2024
49013db
Prefix everything with dev
mike-zorn Jun 24, 2024
0c2dc43
Add project response
mike-zorn Jun 24, 2024
1f199e6
More complete spec
mike-zorn Jun 24, 2024
41d748f
IT LIVES!
mike-zorn Jun 24, 2024
29e82af
add directories
mike-zorn Jun 24, 2024
6bdd657
db works
mike-zorn Jun 24, 2024
e510284
WIP almost create a project
mike-zorn Jun 24, 2024
c306338
almost working create
mike-zorn Jun 24, 2024
90c2cc4
almost can create project from api
mike-zorn Jun 24, 2024
ba9fdc9
types work out now
mike-zorn Jun 24, 2024
1cf389f
fix lint
mike-zorn Jun 24, 2024
cb04568
Set up initial bits of overrides
mike-zorn Jun 25, 2024
42c04b9
add new command to start dev server
k3llymariee Jun 24, 2024
fee4159
add top level dev-server cmd, start subcommand
k3llymariee Jun 24, 2024
9a4d7e9
actually wire it up
k3llymariee Jun 24, 2024
58e9e94
add get and list projects cmds
k3llymariee Jun 24, 2024
1e4401a
add more cmds
k3llymariee Jun 24, 2024
90d4f8b
add remove override cmd
k3llymariee Jun 24, 2024
ae5c240
add dev-services client
k3llymariee Jun 24, 2024
93d76a1
updates for api spec changes
k3llymariee Jun 25, 2024
b1767b7
create ldapi client in RunServer cmd
k3llymariee Jun 25, 2024
0747c2b
fix conflicts
k3llymariee Jun 25, 2024
041e2da
can create project (#329)
mike-zorn Jun 25, 2024
8c4444c
Adding get project by project key (#328)
ld-kyee Jun 25, 2024
4408830
Delete project (#330)
ld-kyee Jun 25, 2024
b6b5535
New type for flag state. First sdk route (#332)
mike-zorn Jun 26, 2024
c06f381
add override (#331)
k3llymariee Jun 26, 2024
72edc87
update ld cli commands (#333)
ld-kyee Jun 26, 2024
e724f8e
Get clientside sdk routes working (#334)
mike-zorn Jun 26, 2024
9ca5a27
Server SDK support (#335)
mike-zorn Jun 26, 2024
378cd25
chore: add a UI package (#336)
kwatkins-ld Jun 26, 2024
9e66b53
Add flag state (#337)
ld-kyee Jun 26, 2024
a555de4
feat: add Launchpad and begin to port Gonfalon overrides UI (#339)
kwatkins-ld Jun 26, 2024
3f3534e
feat: remove mock flags in devserver UI (#340)
kwatkins-ld Jun 26, 2024
67b6c5e
Add overrides to projects (#341)
ld-kyee Jun 26, 2024
f818142
Overrides make streaming updates (#342)
mike-zorn Jun 26, 2024
44f410c
fix: Overrides weren't being loaded when SDKs were initialized (#345)
mike-zorn Jun 27, 2024
cf687ca
[sc-248413] moonshots deploy ld dev server into the dev (#338)
hoshsadiq Jun 27, 2024
314de9f
feat: Add support for flag overrides from the devserver UI (#343)
kwatkins-ld Jun 27, 2024
7273f8d
feat: Move devserver db to XDG_STATE_HOME (#344)
mike-zorn Jun 27, 2024
2848179
feat: add ui routes (#348)
mike-zorn Jun 27, 2024
d8ac832
Adds a sync api (#346)
ld-kyee Jun 27, 2024
8788bbf
add dev stream uri to config file (#347)
k3llymariee Jun 27, 2024
d81e962
feat: add frontend build (#350)
kwatkins-ld Jun 27, 2024
3ac3aa0
fixing overrides
ld-kyee Jun 27, 2024
9a515f5
Add project patch (#352)
ld-kyee Jun 28, 2024
e2cb811
fix: fix override (#354)
hoshsadiq Jun 28, 2024
4e0cdba
add UI cmd (#355)
k3llymariee Jun 28, 2024
99c82f5
feat: add mobile & PHP support (#356)
mike-zorn Jun 28, 2024
0eb9b4f
fix error response expected by ldcli cmds (#357)
k3llymariee Jun 29, 2024
93c4c6f
fix: error handling when project is missing (#360)
mike-zorn Jul 1, 2024
46eeab0
fix: integration tests for go sdk flag delivery (#362)
mike-zorn Jul 3, 2024
6f7fbca
Merge remote-tracking branch 'origin/main' into moonshot-ld-dev-server
mike-zorn Jul 3, 2024
cf8efb9
[sc-248990] check if flag exists before adding override (#349)
k3llymariee Jul 3, 2024
796c61a
upgrade go version to 1.22.
mike-zorn Jul 3, 2024
27222c0
fix: use sync map for observers (#370)
mike-zorn Jul 8, 2024
ddf4190
test: Improve Test Coverage of model package (#367)
tvarney13 Jul 8, 2024
1a67530
fix: add documentation of the build process (#363)
mike-zorn Jul 8, 2024
37dddb6
use resource client instead of separate dev server client (#369)
k3llymariee Jul 8, 2024
7c6597e
feat: Allow for the customization of the port when starting dev serve…
tvarney13 Jul 9, 2024
786c548
feat: Sync publishes streaming update (#371)
tvarney13 Jul 9, 2024
6192201
Abram UI enhancements (#359)
Glacian22 Jul 9, 2024
7972744
feat: Allow customized contexts when creating a project (#374)
tvarney13 Jul 10, 2024
0094020
fix: Improve test coverage of db package (#375)
tvarney13 Jul 10, 2024
9aaa95a
fix: Return 400 if sourceEnvironmentKey is not present in Post endpoi…
tvarney13 Jul 15, 2024
c724bc6
fix: startup logging (#381)
tvarney13 Jul 15, 2024
002f4d0
Merge remote-tracking branch 'origin/main' into moonshot-ld-dev-server
mike-zorn Aug 7, 2024
ce30082
Redirect root on devserver [sc-252320]
mike-zorn Aug 7, 2024
182028f
fix: Don't 500 when there's a preexisting project (#383)
mike-zorn Aug 12, 2024
dcb35fd
Set a better title for the UI.
mike-zorn Aug 12, 2024
0835398
end of file fixes
mike-zorn Aug 12, 2024
c045326
handle error in icon provider
mike-zorn Aug 12, 2024
426c9f1
fix: add credentials to cors (#384)
hoshsadiq Aug 12, 2024
3520ec0
Tweak docs from feedback
mike-zorn Aug 12, 2024
a697c08
Add log message to indicate where the error happened
mike-zorn Aug 12, 2024
7e2403c
Stop hardcoding the port
mike-zorn Aug 12, 2024
6f44423
Improve logs when post 500s [sc-252931]
mike-zorn Aug 12, 2024
b316f34
fix: cross compile binary with CGO to satisfy sqlite3 (#389)
hoshsadiq Aug 14, 2024
1cb8744
Merge remote-tracking branch 'origin/main' into moonshot-ld-dev-server
mike-zorn Aug 14, 2024
e4a353c
Add comment on why goreleaser-cross
mike-zorn Aug 14, 2024
3f1f0aa
Document some goreleaser arcana
mike-zorn Aug 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ The version of this CLI that you are using.
For instance, Ubuntu 16.04, Windows 10, or macOS 14.4.

**Additional context**
Add any other context about the problem here.
Add any other context about the problem here.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ A clear and concise description of what you want to happen.
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context about the feature request here.
Add any other context about the feature request here.
39 changes: 34 additions & 5 deletions .github/actions/publish/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ inputs:
tag:
description: 'Tag to upload artifacts to.'
required: true

outputs:
hashes:
description: sha256sum hashes of built artifacts
Expand All @@ -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="$(
Copy link
Contributor

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

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
Copy link
Contributor

Choose a reason for hiding this comment

The 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 goreleaser-action is no longer being used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
dist/
*.log
node_modules/
devserver.db
65 changes: 49 additions & 16 deletions .goreleaser.yaml
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
Expand All @@ -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=
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Expand All @@ -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:
Expand Down
7 changes: 6 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ repos:
exclude: '^vendor/|^.circleci/image/tools'
name: run-go-tests
- id: discarded-stacktrace
exclude: '(^vendor/)'
exclude: '(^vendor/|.*gen\.go)'
- id: go-mod-tidy
- id: go-mod-verify
- id: go-mod-vendor-no-change
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: end-of-file-fixer
exclude: '^vendor'
3 changes: 0 additions & 3 deletions Dockerfile.goreleaser
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
FROM alpine:3.19.1

RUN apk update
RUN apk add --no-cache git

COPY ldcli /ldcli

LABEL homepage="https://www.launchdarkly.com"
Expand Down
44 changes: 26 additions & 18 deletions cmd/cliflags/flags.go
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,
}
}
2 changes: 2 additions & 0 deletions cmd/config/testdata/help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ Supported settings:
- `access-token`: LaunchDarkly access token with write-level access
- `analytics-opt-out`: Opt out of analytics tracking
- `base-uri`: LaunchDarkly base URI
- `dev-stream-uri`: Streaming service endpoint that the dev server uses to obtain authoritative flag data. This may be a LaunchDarkly or Relay Proxy endpoint
- `environment`: Default environment key
- `flag`: Default feature flag key
- `output`: Command response output format in either JSON or plain text
- `port`: Port for the dev server to run on
- `project`: Default project key

Usage:
Expand Down
60 changes: 60 additions & 0 deletions cmd/dev_server/dev_server.go
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))
}
Loading
Loading