Skip to content

Commit

Permalink
chore: support passing arbitrary env vars to speakeasy cli (#160)
Browse files Browse the repository at this point in the history
* chore: support passing arbitrary env vars to speakeasy cli

* chore: rename to environment

* chore: update tests
  • Loading branch information
ThomasRooney authored Sep 17, 2024
1 parent 2f2db8b commit 2afc16f
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 5 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/workflow-executor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ on:
description: "Version to manually set for SDK generation"
required: false
type: string
environment:
description: |
Any required environment variables to set for the speakeasy run execution. Set as a string with each entry of the form "key=value".
Example:
environment: |
SPECIFICATION_URL=https://api.example.com/swagger.json
Where .speakeasy/workflow.yaml contains:
sources:
my-source:
inputs:
- location: $SPECIFICATION_URL

Note: This should not be used for secrets as inputs will *not* be masked. Something akin to $npm_token should be explicitly passed as a secret.
required: false
type: string
dotnet_version:
description: "The version of dotnet to use when compiling the C# SDK"
required: false
Expand Down Expand Up @@ -160,6 +176,7 @@ jobs:
registry_tags: ${{ inputs.registry_tags }}
push_code_samples_only: ${{ inputs.push_code_samples }}
set_version: ${{ inputs.set_version }}
cli_environment_variables: ${{ inputs.environment }}
- uses: ravsamhq/notify-slack-action@v2
if: always() && env.SLACK_WEBHOOK_URL != ''
with:
Expand Down
9 changes: 7 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# action.yml
name: Speakeasy SDK Workflow Runner Action (alpha)
description: The Speakeasy Generation Action isto be run via the workflows provided in this repo and is not intended to be run directly.
name: Speakeasy SDK Workflow Runner Action
description: The Speakeasy Generation Action is to be run via the workflows provided in this repo and is not intended to be run directly.
inputs:
speakeasy_version:
description: The version of the Speakeasy CLI to use or "latest"
Expand Down Expand Up @@ -87,6 +87,10 @@ inputs:
set_version:
description: "Version to manually set for SDK generation"
required: false
cli_environment_variables:
description: |
Extra environment variables to set for the speakeasy run execution.
required: false
outputs:
publish_python:
description: "Whether the Python SDK will be published to PyPi"
Expand Down Expand Up @@ -190,3 +194,4 @@ runs:
- ${{ inputs.sources }}
- ${{ inputs.code_samples }}
- ${{ inputs.set_version }}
- ${{ inputs.cli_environment_variables }}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ go 1.22.4
require (
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.11.0
github.com/google/go-github/v54 v54.0.0
github.com/google/go-github/v63 v63.0.0
github.com/google/uuid v1.6.0
github.com/hashicorp/go-version v1.6.0
github.com/joho/godotenv v1.5.1
github.com/pb33f/libopenapi v0.14.0
github.com/speakeasy-api/git-diff-parser v0.0.3
github.com/speakeasy-api/sdk-gen-config v1.7.4
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v54 v54.0.0 h1:OZdXwow4EAD5jEo5qg+dGFH2DpkyZvVsAehjvJuUL/c=
github.com/google/go-github/v54 v54.0.0/go.mod h1:Sw1LXWHhXRZtzJ9LI5fyJg9wbQzYvFhW8W5P2yaAQ7s=
github.com/google/go-github/v63 v63.0.0 h1:13xwK/wk9alSokujB9lJkuzdmQuVn2QCPeck76wR3nE=
github.com/google/go-github/v63 v63.0.0/go.mod h1:IqbcrgUmIcEaioWrGYei/09o+ge5vhffGOcxrO0AfmA=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
Expand All @@ -89,6 +87,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
Expand Down
62 changes: 62 additions & 0 deletions internal/cli/run_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cli

import (
"github.com/speakeasy-api/sdk-generation-action/internal/environment"
"os"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -37,3 +39,63 @@ OpenAPI spec validation complete. 0 errors, 1 warnings, 0 hints`,
})
}
}

func Test_environmentVariables(t *testing.T) {
tests := []struct {
name string
input string
expected []string
}{
{
name: "simple case",
input: "FOO=bar",
expected: []string{"FOO=bar"},
},
{
name: "trimmed",
input: " FOO=bar",
expected: []string{"FOO=bar"},
},
{
name: "quotes",
input: `FOO="bar baz"`,
expected: []string{`FOO=bar baz`},
},
{
name: "multi input",
input: "FOO=bar\nBAR=qux",
expected: []string{"BAR=qux", "FOO=bar"},
},
{
name: "quoted input with newline",
input: " FOO=\"foo\nbar\n\"\nother_input=value",
expected: []string{"FOO=foo\nbar\n", "other_input=value"},
},
{
name: "windows newlines",
input: "FOO=bar\r\nBAR=qux",
expected: []string{"BAR=qux", "FOO=bar"},
},
{
name: "empty input",
input: "",
expected: []string{},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set the environment variable
os.Setenv("INPUT_CLI_ENVIRONMENT_VARIABLES", tt.input)

// Call the function
result := environment.SpeakeasyEnvVars()

// Validate the result
assert.Equal(t, tt.expected, result, "The result should match the expected output")

// Clean up
os.Unsetenv("INPUT_CLI_ENVIRONMENT_VARIABLES")
})
}
}
2 changes: 2 additions & 0 deletions internal/cli/speakeasy.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func Download(pinnedVersion string, g Git) (string, error) {

func runSpeakeasyCommand(args ...string) (string, error) {
baseDir := environment.GetBaseDir()
extraRunEnvVars := environment.SpeakeasyEnvVars()

cmdPath := filepath.Join(baseDir, "bin", "speakeasy")

Expand All @@ -84,6 +85,7 @@ func runSpeakeasyCommand(args ...string) (string, error) {
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "SPEAKEASY_RUN_LOCATION=action")
cmd.Env = append(cmd.Env, "SPEAKEASY_ENVIRONMENT=github")
cmd.Env = append(cmd.Env, extraRunEnvVars...)

output, err := cmd.CombinedOutput()
if err != nil {
Expand Down
21 changes: 21 additions & 0 deletions internal/environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package environment

import (
"fmt"
"github.com/joho/godotenv"
"os"
"sort"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -54,6 +56,25 @@ func IsDebugMode() bool {
return os.Getenv("INPUT_DEBUG") == "true" || os.Getenv("RUNNER_DEBUG") == "1"
}

func SpeakeasyEnvVars() []string {
rawEnv := os.Getenv("INPUT_CLI_ENVIRONMENT_VARIABLES")
if len(rawEnv) == 0 {
return []string{}
}
src, err := godotenv.Unmarshal(rawEnv)
if err != nil {
fmt.Printf("Error: Failed to parse env vars from %s: %s\n", rawEnv, err)
return []string{}
}

var result []string
for k, v := range src {
result = append(result, fmt.Sprintf("%s=%s", k, v))
}
sort.Strings(result)
return result
}

func ForceGeneration() bool {
return os.Getenv("INPUT_FORCE") == "true"
}
Expand Down

0 comments on commit 2afc16f

Please sign in to comment.