Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Test

on:
pull_request:
push:
branches:
- main

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: ./go.mod
check-latest: true
cache: true

- name: Install keyring dependencies
run: |
sudo apt-get update
sudo apt-get install -y gnome-keyring dbus-x11

- name: Start D-Bus and keyring
run: |
# Start D-Bus session
eval $(dbus-launch --sh-syntax)
echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" >> $GITHUB_ENV

# Initialize gnome-keyring with a test password
echo 'test' | gnome-keyring-daemon --unlock
eval $(echo 'test' | gnome-keyring-daemon --start --components=secrets)
echo "GNOME_KEYRING_CONTROL=$GNOME_KEYRING_CONTROL" >> $GITHUB_ENV
Comment on lines +24 to +38
Copy link
Member Author

@nathanjcochran nathanjcochran Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was necessary to get the tests that rely on the keyring to pass in CI. Tbh, Claude wrote this code and I didn't take time to understand it, but it did make the tests pass 😅. It's definitely possible that some of this is wonky or unnecessary.


- name: Build
run: go build ./...

- name: Vet
run: go vet ./...

- name: Test
run: go test -p 1 -race -coverprofile=coverage.out -coverpkg=./... ./...

- name: Generate Coverage Report
run: go tool cover -html=coverage.out -o=coverage.html

- name: Upload Coverage Report
uses: actions/upload-artifact@v4
with:
name: coverage.html
path: coverage.html

- name: ShellCheck
run: shellcheck scripts/install.sh
5 changes: 5 additions & 0 deletions internal/tiger/cmd/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"regexp"
"strings"
"testing"
"time"

"github.com/spf13/viper"
"github.com/timescale/tiger-cli/internal/tiger/config"
Expand Down Expand Up @@ -409,6 +410,10 @@ func mockOpenBrowser(t *testing.T) func(string) error {

// Give the OAuth server a moment to start
go func() {
// Sleep to ensure the OAuth callback server is listening
// This prevents "EOF" errors in CI when the server hasn't started yet
time.Sleep(100 * time.Millisecond)

// Make the OAuth callback request directly
callbackURL := fmt.Sprintf("%s?code=test-auth-code&state=%s", redirectURI, state)
t.Logf("Mock browser making callback request to: %s", callbackURL)
Expand Down
6 changes: 6 additions & 0 deletions internal/tiger/config/api_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
func setupAPIKeyTest(t *testing.T) string {
t.Helper()

// Clean up any existing keyring entries before test
RemoveAPIKeyFromKeyring()

// Create temporary directory for test config
tmpDir, err := os.MkdirTemp("", "tiger-api-key-test-*")
if err != nil {
Expand All @@ -21,6 +24,9 @@ func setupAPIKeyTest(t *testing.T) string {
viper.SetConfigFile(GetConfigFile(tmpDir))

t.Cleanup(func() {
// Clean up keyring entries
RemoveAPIKeyFromKeyring()

// Reset global config to ensure test isolation
ResetGlobalConfig()

Expand Down
29 changes: 17 additions & 12 deletions internal/tiger/config/config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package config

import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -63,26 +65,29 @@ func SetupViper(configDir string) error {
viper.SetDefault("password_storage", DefaultPasswordStorage)
viper.SetDefault("debug", DefaultDebug)

// Try to read config file if it exists
if _, err := os.Stat(configFile); err == nil {
// File exists, try to read it
if err := viper.ReadInConfig(); err != nil {
return fmt.Errorf("error reading config file: %w", err)
}
return readInConfig()
}

// Configure viper to watch for file changes and update its in-memory
// representation of the config. Note that this won't automatically
// update [Config] structs already returned from [Load].
viper.WatchConfig()
}
func readInConfig() error {
// Try to read config file if it exists
// If file doesn't exist, that's okay - we'll use defaults and env vars

if err := viper.ReadInConfig(); err != nil &&
!errors.As(err, &viper.ConfigFileNotFoundError{}) &&
!errors.Is(err, fs.ErrNotExist) {
return err
}
return nil
}

// Load creates a new Config instance from the current viper state
// This function should be called after SetupViper has been called to initialize viper
func Load() (*Config, error) {
// Try to read config file into viper to ensure we're unmarshaling the most
// up-to-date values into the config struct.
if err := readInConfig(); err != nil {
return nil, err
}

cfg := &Config{
ConfigDir: GetConfigDir(),
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ verify_checksum() {

# Format checksum for validation: "hash filename"
local formatted_checksum
formatted_checksum=$(printf "%s %s\n" "$(cat "${checksum_file}" | tr -d '[:space:]')" "${filename}")
formatted_checksum=$(printf "%s %s\n" "$(tr -d '[:space:]' < "${checksum_file}")" "${filename}")
Copy link
Member Author

@nathanjcochran nathanjcochran Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addresses https://www.shellcheck.net/wiki/SC2002, which was only showing up in CI because the GitHub Actions ubuntu image includes an older version of shellcheck, and the shellcheck docs say:

This suggestion was enabled by default up to and including ShellCheck 0.10.0.

In later versions, it is optional. It must be explicitly enabled with a directive enable=useless-use-of-cat in a # shellcheck comment or .shellcheckrc


if command -v sha256sum >/dev/null 2>&1; then
if ! echo "${formatted_checksum}" | sha256sum -c - >/dev/null 2>&1; then
Expand Down