Skip to content

Commit 20bf913

Browse files
authored
feat: add picker (#308)
1 parent 35313c5 commit 20bf913

14 files changed

Lines changed: 1113 additions & 138 deletions

File tree

.github/assets/demo.gif

5.26 MB
Loading

.github/workflows/chocolatey.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ jobs:
2323
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'v')) }}
2424
steps:
2525
- name: Checkout
26-
uses: actions/checkout@v4
26+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2727

2828
- name: Unshallow
2929
run: git fetch --prune --unshallow
3030

3131
- name: Get latest release tag
32-
uses: oprypin/find-latest-tag@v1
32+
uses: oprypin/find-latest-tag@dd2729fe78b0bb55523ae2b2a310c6773a652bd1 # v1.1.2
3333
with:
3434
repository: ${{ github.repository }}
3535
releases-only: true
@@ -60,21 +60,21 @@ jobs:
6060
ls -la nuspec/chocolatey/tools/
6161
6262
- name: Choco Downgrade
63-
uses: crazy-max/ghaction-chocolatey@v3
63+
uses: crazy-max/ghaction-chocolatey@2526f467ccbd337d307fe179959cabbeca0bc8c0 # v3.4.0
6464
with:
6565
args: install chocolatey --version=1.2.1 --allow-downgrade -y -r --no-progress
6666

6767
- name: Pack Release
68-
uses: crazy-max/ghaction-chocolatey@v3
68+
uses: crazy-max/ghaction-chocolatey@2526f467ccbd337d307fe179959cabbeca0bc8c0 # v3.4.0
6969
with:
7070
args: pack nuspec/chocolatey/okta-aws-cli.nuspec --outputdirectory nuspec/chocolatey
7171

7272
- name: Choco Upgrade
73-
uses: crazy-max/ghaction-chocolatey@v3
73+
uses: crazy-max/ghaction-chocolatey@2526f467ccbd337d307fe179959cabbeca0bc8c0 # v3.4.0
7474
with:
7575
args: upgrade chocolatey
7676

7777
- name: Upload Release
78-
uses: crazy-max/ghaction-chocolatey@v3
78+
uses: crazy-max/ghaction-chocolatey@2526f467ccbd337d307fe179959cabbeca0bc8c0 # v3.4.0
7979
with:
8080
args: push nuspec/chocolatey/okta-aws-cli.${{ steps.version.outputs.nuget }}.nupkg -s https://push.chocolatey.org/ -k ${{ secrets.CHOCO_API_KEY }}

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- name: Setup Go
1515
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
1616
with:
17-
go-version: 1.21
17+
go-version-file: "go.mod"
1818

1919
- name: Setup Go Tools
2020
run: make tools

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Set up Go
1717
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 #v3.5.0
1818
with:
19-
go-version: 1.21
19+
go-version-file: "go.mod"
2020

2121
- name: Import GPG key
2222
id: import_gpg

README.md

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,23 @@ These settings are optional unless marked otherwise:
578578
| Authorization Server ID | The ID of the Okta authorization server, set ID for a custom authorization server, will use default otherwise. Default `default` | `--authz-id [value]` | `OKTA_AWSCLI_AUTHZ_ID` |
579579
| Custom STS Role Session Name | Customize STS Role Session Name. Default `okta-aws-cli` | `--aws-sts-role-session-name [value]` | `OKTA_AWSCLI_STS_ROLE_SESSION_NAME` |
580580

581+
### Interactive Selection with Fuzzy Search
582+
583+
When multiple IdPs or Roles are available, `okta-aws-cli` presents an interactive
584+
picker with fuzzy search capabilities. This makes it easy to find the right
585+
option even when you have many roles configured.
586+
587+
![Fuzzy Search Picker Demo](.github/assets/demo.gif)
588+
589+
**Features:**
590+
- **Fuzzy search**: Type to filter options - matches are highlighted
591+
- **Smart filtering**: Search is performed on the role/IdP name only (the part after the last `/`), not the full ARN
592+
- **Keyboard navigation**: Use ``/`` arrows to navigate, `Enter` to select, `Esc` to cancel
593+
- **Scroll indicators**: Shows count of items above/below when list is long
594+
595+
When typing `dev`, only roles containing "dev" in the role name will be shown,
596+
with the matching characters highlighted.
597+
581598
### Friendly IdP and Role menu labels
582599

583600
When the operator has many AWS Federation apps listing the AWS IAM IdP ARNs can
@@ -591,18 +608,28 @@ and Roles can also be evaluated are regular expressions (see example below).
591608
`$HOME/.okta/okta.yaml` as a configuration file and location. We will continue
592609
that practice with read-only friendly okta-aws-cli application values.
593610

594-
#### Before
611+
#### Before (without friendly labels)
595612

596613
```
597-
? Choose an IdP: [Use arrows to move, type to filter]
614+
? Choose an IdP:
615+
616+
> Type to filter...
617+
598618
> Fed App 1 Label
599619
Fed App 2 Label
600620
Fed App 3 Label
601621
Fed App 4 Label
602622
603-
? Choose a Role: [Use arrows to move, type to filter]
623+
(esc to cancel)
624+
625+
? Choose a Role:
626+
627+
> Type to filter...
628+
604629
> arn:aws:iam::123456789012:role/admin
605630
arn:aws:iam::123456789012:role/ops
631+
632+
(esc to cancel)
606633
```
607634

608635
#### Example `$HOME/.okta/okta.yaml`
@@ -620,18 +647,28 @@ awscli:
620647
"arn:aws:iam::.*:role/operator": "Ops"
621648
```
622649
623-
#### After
650+
#### After (with friendly labels from okta.yaml)
624651
625652
```
626-
? Choose an IdP: [Use arrows to move, type to filter]
653+
? Choose an IdP:
654+
655+
> Type to filter...
656+
627657
> Data Production
628658
Data Development
629659
Marketing Production
630660
Marketing Development
631661

632-
? Choose a Role: [Use arrows to move, type to filter]
662+
(esc to cancel)
663+
664+
? Choose a Role:
665+
666+
> Type to filter...
667+
633668
> Admin
634669
Ops
670+
671+
(esc to cancel)
635672
```
636673

637674
### Configuration by profile name

examples/picker_demo.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
/*
5+
* Copyright (c) 2026-Present, Okta, Inc.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
// This is a demo script to showcase the fuzzy search picker functionality.
21+
// Run this demo to see how the picker works with example AWS IAM roles.
22+
//
23+
// Usage:
24+
//
25+
// go run examples/picker_demo.go
26+
package main
27+
28+
import (
29+
"fmt"
30+
"os"
31+
32+
"github.com/okta/okta-aws-cli/v2/internal/picker"
33+
)
34+
35+
func main() {
36+
// Example AWS IAM roles with fake account IDs for demonstration
37+
roles := []string{
38+
"arn:aws:iam::123456789012:role/Admin",
39+
"arn:aws:iam::123456789012:role/Developer",
40+
"arn:aws:iam::123456789012:role/ReadOnly",
41+
"arn:aws:iam::123456789012:role/DevOps-Engineer",
42+
"arn:aws:iam::123456789012:role/Security-Analyst",
43+
"arn:aws:iam::987654321098:role/Production-Admin",
44+
"arn:aws:iam::987654321098:role/Production-Developer",
45+
"arn:aws:iam::987654321098:role/Production-ReadOnly",
46+
"arn:aws:iam::111222333444:role/Staging-Admin",
47+
"arn:aws:iam::111222333444:role/Staging-Developer",
48+
"arn:aws:iam::555666777888:role/QA-Tester",
49+
"arn:aws:iam::555666777888:role/QA-Lead",
50+
"arn:aws:iam::999000111222:role/Data-Engineer",
51+
"arn:aws:iam::999000111222:role/Data-Scientist",
52+
"arn:aws:iam::999000111222:role/ML-Engineer",
53+
}
54+
55+
fmt.Println("=== Okta AWS CLI - Fuzzy Search Picker Demo ===")
56+
fmt.Println()
57+
fmt.Println("Tips:")
58+
fmt.Println(" • Type to filter roles (searches role name, not full ARN)")
59+
fmt.Println(" • Use ↑/↓ arrows to navigate")
60+
fmt.Println(" • Press Enter to select")
61+
fmt.Println(" • Press Esc to cancel")
62+
fmt.Println()
63+
64+
selected, err := picker.Pick("Choose an AWS IAM Role:", roles)
65+
if err != nil {
66+
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
67+
os.Exit(1)
68+
}
69+
70+
fmt.Println()
71+
fmt.Printf("✓ Selected: %s\n", selected)
72+
}

go.mod

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,63 @@
11
module github.com/okta/okta-aws-cli/v2
22

3-
go 1.21
3+
go 1.24.2
44

55
require (
6-
github.com/AlecAivazis/survey/v2 v2.3.6
76
github.com/BurntSushi/toml v1.4.0
87
github.com/aws/aws-sdk-go v1.55.5
98
github.com/cenkalti/backoff/v4 v4.1.3
9+
github.com/charmbracelet/bubbles v1.0.0
10+
github.com/charmbracelet/bubbletea v1.3.10
11+
github.com/charmbracelet/lipgloss v1.1.0
1012
github.com/go-jose/go-jose/v4 v4.0.4
1113
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
1214
github.com/google/uuid v1.1.2
1315
github.com/logrusorgru/aurora v2.0.3+incompatible
14-
github.com/mattn/go-isatty v0.0.16
16+
github.com/mattn/go-isatty v0.0.20
1517
github.com/mdp/qrterminal v1.0.1
1618
github.com/ompluscator/dynamic-struct v1.4.0
1719
github.com/pkg/errors v0.9.1
20+
github.com/sahilm/fuzzy v0.1.1
1821
github.com/spf13/cobra v1.5.0
1922
github.com/spf13/viper v1.14.0
2023
github.com/stretchr/testify v1.9.0
2124
github.com/tidwall/pretty v1.2.0
22-
golang.org/x/net v0.34.0
23-
golang.org/x/sys v0.29.0
25+
golang.org/x/net v0.49.0
26+
golang.org/x/sys v0.41.0
2427
gopkg.in/dnaeon/go-vcr.v3 v3.1.2
2528
gopkg.in/ini.v1 v1.67.0
2629
gopkg.in/yaml.v2 v2.4.0
2730
)
2831

29-
require golang.org/x/crypto v0.32.0 // indirect
32+
require (
33+
github.com/atotto/clipboard v0.1.4 // indirect
34+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
35+
github.com/charmbracelet/colorprofile v0.4.1 // indirect
36+
github.com/charmbracelet/x/ansi v0.11.6 // indirect
37+
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
38+
github.com/charmbracelet/x/term v0.2.2 // indirect
39+
github.com/clipperhouse/displaywidth v0.9.0 // indirect
40+
github.com/clipperhouse/stringish v0.1.1 // indirect
41+
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
42+
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
43+
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
44+
github.com/mattn/go-localereader v0.0.1 // indirect
45+
github.com/mattn/go-runewidth v0.0.19 // indirect
46+
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
47+
github.com/muesli/cancelreader v0.2.2 // indirect
48+
github.com/muesli/termenv v0.16.0 // indirect
49+
github.com/rivo/uniseg v0.4.7 // indirect
50+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
51+
golang.org/x/crypto v0.48.0 // indirect
52+
)
3053

3154
require (
3255
github.com/davecgh/go-spew v1.1.1 // indirect
3356
github.com/fsnotify/fsnotify v1.6.0 // indirect
3457
github.com/hashicorp/hcl v1.0.0 // indirect
3558
github.com/inconshreveable/mousetrap v1.0.1 // indirect
3659
github.com/jmespath/go-jmespath v0.4.0 // indirect
37-
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
3860
github.com/magiconair/properties v1.8.7 // indirect
39-
github.com/mattn/go-colorable v0.1.12 // indirect
40-
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
4161
github.com/mitchellh/mapstructure v1.5.0 // indirect
4262
github.com/pelletier/go-toml v1.9.5 // indirect
4363
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
@@ -48,8 +68,7 @@ require (
4868
github.com/spf13/jwalterweatherman v1.1.0 // indirect
4969
github.com/spf13/pflag v1.0.5 // indirect
5070
github.com/subosito/gotenv v1.4.2 // indirect
51-
golang.org/x/term v0.28.0 // indirect
52-
golang.org/x/text v0.21.0 // indirect
71+
golang.org/x/text v0.34.0 // indirect
5372
gopkg.in/yaml.v3 v3.0.1 // indirect
5473
rsc.io/qr v0.2.0 // indirect
5574
)

0 commit comments

Comments
 (0)