claude-aws-mfa 1.1.0-rc.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +139 -0
- package/CHANGELOG.md +55 -0
- package/README.md +27 -0
- package/package.json +1 -1
- package/.github/workflows/publish.yml +0 -76
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
name: Release from Changelog
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
detect-release:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
outputs:
|
|
12
|
+
version: ${{ steps.parse.outputs.version }}
|
|
13
|
+
prerelease: ${{ steps.parse.outputs.prerelease }}
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-tags: true
|
|
18
|
+
|
|
19
|
+
- name: Parse latest changelog version
|
|
20
|
+
id: parse
|
|
21
|
+
run: |
|
|
22
|
+
# Extract the first heading that matches: ## [vX.Y.Z...] - YYYY-MM-DD
|
|
23
|
+
# The date is required — headings without a date are treated as drafts.
|
|
24
|
+
HEADING=$(grep -P '^## \[v[^\]]+\]\s+-\s+\d{4}-\d{2}-\d{2}' CHANGELOG.md | head -1)
|
|
25
|
+
|
|
26
|
+
if [ -z "$HEADING" ]; then
|
|
27
|
+
echo "No dated release heading found — nothing to release."
|
|
28
|
+
echo "version=" >> "$GITHUB_OUTPUT"
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
VERSION=$(echo "$HEADING" | grep -oP '(?<=\[)[^\]]+')
|
|
33
|
+
|
|
34
|
+
# Must be valid semver with v prefix
|
|
35
|
+
if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9._-]+)?$ ]]; then
|
|
36
|
+
echo "::error::First changelog heading '$VERSION' is not valid semver with v prefix"
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Verify the date is today (UTC +/- 12h to accommodate any timezone)
|
|
41
|
+
ENTRY_DATE=$(echo "$HEADING" | grep -oP '\d{4}-\d{2}-\d{2}')
|
|
42
|
+
YESTERDAY=$(date -u -d '-12 hours' +%Y-%m-%d)
|
|
43
|
+
TODAY=$(date -u +%Y-%m-%d)
|
|
44
|
+
TOMORROW=$(date -u -d '+12 hours' +%Y-%m-%d)
|
|
45
|
+
if [[ "$ENTRY_DATE" != "$YESTERDAY" && "$ENTRY_DATE" != "$TODAY" && "$ENTRY_DATE" != "$TOMORROW" ]]; then
|
|
46
|
+
echo "::error::Changelog date $ENTRY_DATE does not match today — expected $YESTERDAY, $TODAY, or $TOMORROW"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Check if this tag already exists on the remote
|
|
51
|
+
if git rev-parse "refs/tags/$VERSION" >/dev/null 2>&1; then
|
|
52
|
+
echo "Tag $VERSION already exists — skipping release."
|
|
53
|
+
echo "version=" >> "$GITHUB_OUTPUT"
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Check if a GitHub release already exists
|
|
58
|
+
if gh release view "$VERSION" >/dev/null 2>&1; then
|
|
59
|
+
echo "::error::GitHub release $VERSION already exists but tag does not — manual cleanup needed"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
PRERELEASE="false"
|
|
64
|
+
SEMVER="${VERSION#v}"
|
|
65
|
+
if [[ "$SEMVER" =~ - ]]; then
|
|
66
|
+
PRERELEASE="true"
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
70
|
+
echo "prerelease=$PRERELEASE" >> "$GITHUB_OUTPUT"
|
|
71
|
+
echo "Detected version=$VERSION prerelease=$PRERELEASE"
|
|
72
|
+
|
|
73
|
+
release:
|
|
74
|
+
needs: detect-release
|
|
75
|
+
if: needs.detect-release.outputs.version != ''
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
permissions:
|
|
78
|
+
contents: read
|
|
79
|
+
id-token: write
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v4
|
|
82
|
+
with:
|
|
83
|
+
token: ${{ secrets.RELEASE_PAT }}
|
|
84
|
+
|
|
85
|
+
- uses: oven-sh/setup-bun@v2
|
|
86
|
+
with:
|
|
87
|
+
bun-version: latest
|
|
88
|
+
|
|
89
|
+
- run: bun install --frozen-lockfile
|
|
90
|
+
|
|
91
|
+
- run: bun test
|
|
92
|
+
|
|
93
|
+
- name: Set package version
|
|
94
|
+
run: |
|
|
95
|
+
VERSION="${{ needs.detect-release.outputs.version }}"
|
|
96
|
+
npm version "${VERSION#v}" --no-git-tag-version
|
|
97
|
+
|
|
98
|
+
- name: Extract changelog entry
|
|
99
|
+
id: changelog
|
|
100
|
+
run: |
|
|
101
|
+
VERSION="${{ needs.detect-release.outputs.version }}"
|
|
102
|
+
# Extract the body of the first changelog section (between first ## and second ##)
|
|
103
|
+
BODY=$(awk '/^## \[/{if(found) exit; found=1; next} found' CHANGELOG.md)
|
|
104
|
+
# Write to file for the release body
|
|
105
|
+
echo "$BODY" > /tmp/release-body.md
|
|
106
|
+
|
|
107
|
+
- name: Create Git tag
|
|
108
|
+
run: |
|
|
109
|
+
VERSION="${{ needs.detect-release.outputs.version }}"
|
|
110
|
+
git tag "$VERSION"
|
|
111
|
+
git push origin "$VERSION"
|
|
112
|
+
|
|
113
|
+
- name: Create GitHub Release
|
|
114
|
+
env:
|
|
115
|
+
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
|
|
116
|
+
run: |
|
|
117
|
+
VERSION="${{ needs.detect-release.outputs.version }}"
|
|
118
|
+
PRERELEASE="${{ needs.detect-release.outputs.prerelease }}"
|
|
119
|
+
FLAGS=""
|
|
120
|
+
if [ "$PRERELEASE" = "true" ]; then
|
|
121
|
+
FLAGS="--prerelease"
|
|
122
|
+
fi
|
|
123
|
+
gh release create "$VERSION" \
|
|
124
|
+
--title "$VERSION" \
|
|
125
|
+
--notes-file /tmp/release-body.md \
|
|
126
|
+
$FLAGS
|
|
127
|
+
|
|
128
|
+
- uses: actions/setup-node@v4
|
|
129
|
+
with:
|
|
130
|
+
node-version: 24
|
|
131
|
+
registry-url: https://registry.npmjs.org
|
|
132
|
+
|
|
133
|
+
- name: Publish to npm
|
|
134
|
+
run: |
|
|
135
|
+
TAG="latest"
|
|
136
|
+
if [ "${{ needs.detect-release.outputs.prerelease }}" = "true" ]; then
|
|
137
|
+
TAG="next"
|
|
138
|
+
fi
|
|
139
|
+
npm publish --access public --tag "$TAG"
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
|
+
|
|
8
|
+
### Releasing
|
|
9
|
+
|
|
10
|
+
Releases are automated via CI. To create a new release:
|
|
11
|
+
|
|
12
|
+
1. Add a new entry at the top of this file with heading `## [vX.Y.Z]` (without a
|
|
13
|
+
date). This is a draft — it can be merged to `main` without triggering a
|
|
14
|
+
release.
|
|
15
|
+
2. When ready to publish, update the heading to `## [vX.Y.Z] - YYYY-MM-DD` and
|
|
16
|
+
merge to `main`. The date signals "ready to release".
|
|
17
|
+
3. The workflow will run tests, create a Git tag, GitHub Release, and npm publish.
|
|
18
|
+
4. If the tag already exists, the workflow skips (safe to re-merge).
|
|
19
|
+
5. If tests fail, no tag/release is created. The release will be re-attempted on
|
|
20
|
+
each subsequent push to `main`, or can be manually retried from the Actions UI.
|
|
21
|
+
|
|
22
|
+
Stable versions (e.g. `v1.2.0`) publish to npm `@latest`. Pre-release versions
|
|
23
|
+
(e.g. `v1.2.0-rc.1`) publish to npm `@next` and create a GitHub pre-release.
|
|
24
|
+
|
|
25
|
+
## [v1.1.0] - 2026-06-04
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- **Session caching** (`--cache-session`): Cache STS session credentials in the config file and reuse them until they expire, avoiding repeated MFA prompts.
|
|
29
|
+
- **Auto-MFA** (`--auto-mfa`): Automatically run the configured MFA command to obtain credentials without showing the dialog. Falls back to the dialog if the command fails.
|
|
30
|
+
- **Single-instance lock** (`--single-instance-lock`): Prevent multiple concurrent instances from showing overlapping dialogs. Subsequent invocations wait for the first to finish and reuse its cached session.
|
|
31
|
+
- New CLI flags with `--no-` negation support for all new options.
|
|
32
|
+
- New config file options: `cacheSession`, `autoMfa`, `singleInstanceLock`.
|
|
33
|
+
- Tests for session caching, lock mechanism, and CLI flag parsing.
|
|
34
|
+
- CHANGELOG.md to track project changes.
|
|
35
|
+
- Updated README with documentation for new CLI flags and features.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- Automated release pipeline: releases are now triggered by changelog entries pushed to `main`, replacing the previous manual GitHub Release workflow.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- Release workflow: use `RELEASE_PAT` via `actions/checkout` token so git credential helper authenticates with the PAT instead of the default `GITHUB_TOKEN` (which cannot bypass tag rulesets).
|
|
42
|
+
|
|
43
|
+
## [v1.0.0] - 2026-03-28
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
- Initial stable release.
|
|
47
|
+
- Native GUI dialog for AWS credential and MFA code entry.
|
|
48
|
+
- MFA Command mode: provide a shell command (e.g. `op item get --otp …`) to fetch TOTP codes automatically.
|
|
49
|
+
- Automatic STS session duration negotiation (12h → 6h → 2h → 1h).
|
|
50
|
+
- Guided setup wizard (`--setup`) for Claude Code Bedrock configuration.
|
|
51
|
+
- Configuration persistence in `~/.config/claude-aws-mfa.json` (mode 0600).
|
|
52
|
+
- Credential masking in error output.
|
|
53
|
+
- Cross-platform support (macOS, Linux, Windows).
|
|
54
|
+
- CI test workflows (unit + GUI screenshot tests).
|
|
55
|
+
- npm publish workflow triggered by GitHub Releases.
|
package/README.md
CHANGED
|
@@ -32,6 +32,17 @@ Add this (plus any addtitional config you prefer) to your Claude Code settings (
|
|
|
32
32
|
}
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
## CLI Flags
|
|
36
|
+
|
|
37
|
+
All flags can be negated with a `--no-` prefix (e.g. `--no-cache-session`). CLI flags override values saved in the config file.
|
|
38
|
+
|
|
39
|
+
| Flag | Description |
|
|
40
|
+
|------|-------------|
|
|
41
|
+
| `--setup` | Launch the guided setup wizard |
|
|
42
|
+
| `--cache-session` | Cache STS session credentials and reuse them until they expire |
|
|
43
|
+
| `--auto-mfa` | Automatically run the configured MFA command and obtain credentials without showing the dialog (requires MFA Command mode) |
|
|
44
|
+
| `--single-instance-lock` | Prevent multiple concurrent instances from showing overlapping dialogs; subsequent invocations wait for the first to finish and reuse its cached session |
|
|
45
|
+
|
|
35
46
|
## How it works
|
|
36
47
|
|
|
37
48
|
1. On first run, seeds the dialog with credentials from your existing AWS config (`~/.aws/credentials`, environment variables, SSO, etc.)
|
|
@@ -44,6 +55,18 @@ Add this (plus any addtitional config you prefer) to your Claude Code settings (
|
|
|
44
55
|
|
|
45
56
|
On subsequent runs, all fields are pre-populated from the saved config — just enter a fresh MFA code and hit OK. If you use the command mode, the TOTP code is fetched automatically so no manual entry is needed at all.
|
|
46
57
|
|
|
58
|
+
### Session caching
|
|
59
|
+
|
|
60
|
+
With `--cache-session` (or `"cacheSession": true` in the config file), temporary credentials are saved to the config file and reused on subsequent runs until they expire. This avoids prompting for MFA on every invocation.
|
|
61
|
+
|
|
62
|
+
### Auto-MFA
|
|
63
|
+
|
|
64
|
+
With `--auto-mfa` (or `"autoMfa": true` in the config file), when a MFA command is configured, credentials are obtained automatically without showing the dialog at all. If the command fails or isn't configured, the dialog is shown as a fallback.
|
|
65
|
+
|
|
66
|
+
### Single-instance lock
|
|
67
|
+
|
|
68
|
+
With `--single-instance-lock` (or `"singleInstanceLock": true` in the config file), only one instance of the tool will show a dialog at a time. Additional invocations will wait for the first to finish and then reuse its cached session (when session caching is also enabled). The lock file is stored at `~/.config/claude-aws-mfa.lock` and is automatically cleaned up after 2 minutes if the holding process crashes.
|
|
69
|
+
|
|
47
70
|
## System requirements
|
|
48
71
|
|
|
49
72
|
The GUI dialog uses [webview-bun](https://github.com/tr1ckydev/webview-bun), which requires:
|
|
@@ -60,6 +83,10 @@ bun run src/index.ts # run locally
|
|
|
60
83
|
bun test # run tests
|
|
61
84
|
```
|
|
62
85
|
|
|
86
|
+
## Releasing
|
|
87
|
+
|
|
88
|
+
See the [Releasing section of CHANGELOG.md](CHANGELOG.md#releasing) for how to publish new versions.
|
|
89
|
+
|
|
63
90
|
## License
|
|
64
91
|
|
|
65
92
|
MIT
|
package/package.json
CHANGED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: [published]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
publish:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
permissions:
|
|
11
|
-
contents: read
|
|
12
|
-
id-token: write
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- uses: actions/checkout@v4
|
|
16
|
-
|
|
17
|
-
- name: Validate release tag
|
|
18
|
-
run: |
|
|
19
|
-
TAG="${GITHUB_REF_NAME}"
|
|
20
|
-
IS_PRERELEASE="${{ github.event.release.prerelease }}"
|
|
21
|
-
|
|
22
|
-
# Must start with "v"
|
|
23
|
-
if [[ "$TAG" != v* ]]; then
|
|
24
|
-
echo "::error::Tag must start with 'v' (got '$TAG')"
|
|
25
|
-
exit 1
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
VERSION="${TAG#v}"
|
|
29
|
-
|
|
30
|
-
# Must be valid semver (X.Y.Z or X.Y.Z-prerelease)
|
|
31
|
-
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9._-]+)?$ ]]; then
|
|
32
|
-
echo "::error::Tag must be a valid semver with a 'v' prefix (got '$TAG')"
|
|
33
|
-
exit 1
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
HAS_PRERELEASE_SUFFIX="false"
|
|
37
|
-
if [[ "$VERSION" =~ - ]]; then
|
|
38
|
-
HAS_PRERELEASE_SUFFIX="true"
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
# Prerelease checkbox must match tag format
|
|
42
|
-
if [ "$IS_PRERELEASE" = "true" ] && [ "$HAS_PRERELEASE_SUFFIX" = "false" ]; then
|
|
43
|
-
echo "::error::Release is marked as prerelease but tag '$TAG' has no prerelease suffix (e.g. v1.0.0-beta.1)"
|
|
44
|
-
exit 1
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
if [ "$IS_PRERELEASE" = "false" ] && [ "$HAS_PRERELEASE_SUFFIX" = "true" ]; then
|
|
48
|
-
echo "::error::Tag '$TAG' has a prerelease suffix but release is not marked as prerelease"
|
|
49
|
-
exit 1
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
|
|
53
|
-
|
|
54
|
-
- uses: oven-sh/setup-bun@v2
|
|
55
|
-
with:
|
|
56
|
-
bun-version: latest
|
|
57
|
-
|
|
58
|
-
- run: bun install --frozen-lockfile
|
|
59
|
-
|
|
60
|
-
- run: bun test
|
|
61
|
-
|
|
62
|
-
- name: Set package version from release tag
|
|
63
|
-
run: npm version "$VERSION" --no-git-tag-version
|
|
64
|
-
|
|
65
|
-
- uses: actions/setup-node@v4
|
|
66
|
-
with:
|
|
67
|
-
node-version: 24
|
|
68
|
-
registry-url: https://registry.npmjs.org
|
|
69
|
-
|
|
70
|
-
- name: Publish to npm
|
|
71
|
-
run: |
|
|
72
|
-
TAG="latest"
|
|
73
|
-
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
|
|
74
|
-
TAG="next"
|
|
75
|
-
fi
|
|
76
|
-
npm publish --access public --tag "$TAG"
|