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
49 changes: 39 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
# Test on common OSes. Add more if nsyte supports them and has releases.
os: [ubuntu-latest, macos-latest, windows-latest]
# Use 'latest' to test the version resolution logic
nsyte_version: ['latest']
version: ['latest']

steps:
- name: Checkout Repository
Expand All @@ -33,34 +33,55 @@ jobs:
mkdir test-dist
echo "<html>Test index.html</html>" > test-dist/index.html
echo "<html>Test fallback.html</html>" > test-dist/fallback.html
echo "DUMMY_SEC=nbunksec1fakebunkersecretstringforactiontestingpurposesonly" >> $GITHUB_ENV
echo "DUMMY_NBUNKSEC=nbunksec1fakebunkersecretstringforactiontestingpurposesonly" >> $GITHUB_ENV
echo "DUMMY_SEC1=sec1fakeprivatekeystringforvalidationtestingonly" >> $GITHUB_ENV

- name: Run nsite-action (Local Path)
uses: ./
id: test_run
env:
GH_TOKEN: ${{ github.token }}
with:
sec: ${{ env.DUMMY_SEC }}
nbunksec: ${{ env.DUMMY_NBUNKSEC }}
directory: './test-dist'
nsyte_version: ${{ matrix.nsyte_version }}
version: ${{ matrix.version }}
relays: |
wss://nostr.example.com
wss://relay.example.org
servers: |
wss://blossom.example.com
https://blossom.example.com
force: true
verbose: true
fallback: '/fallback.html'
concurrency: 2
continue-on-error: true # Expect failure with dummy nbunksec/relays/servers
continue-on-error: true # Expect failure with dummy signing secret/relays/servers

- name: Reject sec1 value in nbunksec input
uses: ./
id: reject_sec1
env:
GH_TOKEN: ${{ github.token }}
with:
nbunksec: ${{ env.DUMMY_SEC1 }}
directory: './test-dist'
version: ${{ matrix.version }}
continue-on-error: true

- name: Verify Action Attempted Run
shell: bash
run: |
echo "Action step outcome: ${{ steps.test_run.outcome }}"
echo "Action step conclusion: ${{ steps.test_run.conclusion }}"
echo "Action outputs from test_run step:"
echo " Status: ${{ steps.test_run.outputs.status }}"
echo " nsyte Version Used: ${{ steps.test_run.outputs.nsyte_version_used }}"

if [[ "${{ steps.test_run.outcome }}" != "failure" ]]; then
echo "::error::Expected the action step outcome to be 'failure' when nsyte exits non-zero, but got '${{ steps.test_run.outcome }}'."
exit 1
else
echo "Action step outcome correctly reported as 'failure'."
fi

if [[ -z "${{ steps.test_run.outputs.nsyte_version_used }}" ]]; then
echo "::error::Output 'nsyte_version_used' was NOT set."
Expand All @@ -77,9 +98,17 @@ jobs:
echo "Status output correctly set to 'failure'."
fi

# Check if the version used is the expected latest (v0.5.3) when input is 'latest'
if [[ "${{ inputs.nsyte_version }}" == "latest" && "${{ steps.test_run.outputs.nsyte_version_used }}" != "v0.5.3" ]]; then
echo "::warning::Latest version detected was ${{ steps.test_run.outputs.nsyte_version_used }}, expected v0.5.3. Check nsyte release tagging or the action's version resolution logic."
# Check if the version used resolves to the current latest stable release when input is 'latest'
if [[ "${{ matrix.version }}" == "latest" && "${{ steps.test_run.outputs.nsyte_version_used }}" != "v0.23.0" ]]; then
echo "::warning::Latest stable version detected was ${{ steps.test_run.outputs.nsyte_version_used }}, expected v0.23.0. Check nsyte release tagging or the action's version resolution logic."
# Not failing the test for this warning, but it's important to note.
fi
echo "Verification passed: Outputs are populated, and status is 'failure' as expected with dummy inputs."

if [[ "${{ steps.reject_sec1.outcome }}" != "failure" ]]; then
echo "::error::Expected the invalid nbunksec step to fail, but got '${{ steps.reject_sec1.outcome }}'."
exit 1
else
echo "Invalid nbunksec value was correctly rejected."
fi

echo "Verification passed: Outputs are populated, and status is 'failure' as expected with dummy inputs."
79 changes: 46 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,60 @@
<!-- [![GitHub release (latest by date)](https://img.shields.io/github/v/release/your-username/nsite-action)](https://github.com/your-username/nsite-action/releases)
[![GitHub Actions CI](https://github.com/your-username/nsite-action/actions/workflows/test.yml/badge.svg)](https://github.com/your-username/nsite-action/actions/workflows/test.yml) -->

Deploy static websites to Blossom/Nostr in a Github Actions Workflow, powered by [nsyte](https://github.com/sandwichfarm/nsyte).
Deploy static websites to Blossom/Nostr in a GitHub Actions workflow, powered by [nsyte](https://github.com/sandwichfarm/nsyte).

## Dependencies
- Bunker Signer (NIP-46) for establishing a handshake
- [nsyte](http://github.com/sandwichfarm/nsyte) - For generating an `nbunksec` bunker secret key.
- [nsyte](https://github.com/sandwichfarm/nsyte) - For generating a signing credential with `nsyte ci`.

## Quick Start

1. **Setup nsyte locally** (one-time):
```bash
nsyte ci
```
Follow prompts for Nostr Connect and it will display an **nbunksec**; this is a revocable credential, but still treat it as a secret.
Follow the Nostr Connect prompts and `nsyte` will display a signing credential such as `nbunksec1...`; pass that value to this action via `nbunksec`. Do not paste a `sec1...` private key into this action.

2. **Add GitHub Secret**:
- Add the `nbunksec` string as a repository secret named `NBUNKSEC`
- Add the generated credential as a repository secret, for example `NBUNK_SECRET`

3. **Add to workflow**:
```yaml
- name: Deploy to Nostr/Blossom
uses: sandwichfarm/nsite-action@v0.2.2
with:
nbunksec: ${{ secrets.NBUNKSEC }}
directory: './dist' # Your built website directory
relays: |
wss://relay.nsite.lol
servers: |
https://cdn.hzrd149.com
https://cdn.sovbit.host
```
```yaml
- name: Deploy to Nostr/Blossom
uses: sandwichfarm/nsite-action@v0.2.2
with:
nbunksec: ${{ secrets.NBUNK_SECRET }}
directory: './dist' # Your built website directory
version: 'v0.23.0'
relays: |
wss://relay.nsite.lol
servers: |
https://cdn.hzrd149.com
https://cdn.sovbit.host
```

## Inputs

| Input | Required | Default | Description |
|-------|----------|---------|-------------|
| `nbunksec` | Yes | - | Bunker auth string (store as GitHub Secret) |
| `version` | No | `latest` | nsyte release tag to download (for example `v0.23.0`) |
| `nbunksec` | No | - | Recommended CI credential. Must start with `nbunksec1`. This action rejects `sec1` values for this input. |
| `directory` | Yes | - | Directory containing website files |
| `relays` | Yes | - | Newline separated relay URIs |
| `servers` | Yes | - | Newline separated server URIs |
| `nsyte_version` | No | latest | Version tag (e.g., "v0.5.0") |
| `relays` | No | `''` | Newline-separated relay URIs |
| `servers` | No | `''` | Newline-separated Blossom server URIs |
| `force` | No | false | Re-upload all files |
| `purge` | No | false | Delete remote files not present locally |
| `purge` | No | false | Deprecated; there is no deploy-time `--purge` flag in `nsyte` |
| `sync` | No | false | Check all servers and upload missing blobs |
| `verbose` | No | false | Show detailed output |
| `concurrency` | No | 4 | Number of parallel uploads |
| `fallback` | No | '' | Fallback HTML path (e.g., "/index.html") |
| `publish_server_list` | No | false | use this for new/fresh npubs without blossom servers configured |
| `publish_relay_list` | No | false | use this for new/fresh npubs without relays configured |
| `publish_profile` | No | false | use this for new/fresh npubs without a profile configured |
| `publish_server_list` | No | false | Publish configured servers for fresh identities |
| `publish_relay_list` | No | false | Publish configured relays for fresh identities |
| `publish_profile` | No | false | Publish profile metadata for fresh identities |
| `use_fallback_relays` | No | false | Include nsyte default relays in addition to configured relays |
| `use_fallback_servers` | No | false | Include nsyte default servers in addition to configured servers |
| `publish_app_handler` | No | false | Publish a NIP-89 app handler announcement |
| `handler_kinds` | No | `''` | Comma-separated event kinds for the app handler |

## Outputs

Expand All @@ -64,21 +70,28 @@ Deploy static websites to Blossom/Nostr in a Github Actions Workflow, powered by
- Downloads nsyte binary automatically
- Supports Linux, macOS, and Windows
- Masks sensitive secrets in logs
- Authenticates via NIP-46 bunker
- Accepts the safer `nbunksec` action input and passes it through to nsyte

## Credential Revocation

- Revocation is handled by your bunker signer of choice (NIP-46).
- If you leak your signing credential, rotate it immediately.
- Rotate credentials periodically: revoke the old credential, establish a new connection, and update your GitHub secret.

## `nbunksec` Revocation
## No Warranty

- Revocation is handled by your Bunker Signer of choice (NIP-46).
- If you leak your `nbunksec` you should rotate your keys.
- keys should be rotated periodically (revoke old `nbunksec`, establish a new connection and update secrets)
- This action is provided without warranty of any kind, express or implied.
- If a signing credential or private key is exposed, any resulting loss, impersonation, or irreversible publish action is your responsibility.
- Nostr events and published site data may be replicated by relays and other infrastructure; compromise and publication are not generally revocable.

## Security Notes

- **DO NOT** store `nbunksec` as an environment variable or commit to source code
- Store `nbunksec` as a GitHub Secret
- **DO NOT** paste a `sec1...` private key into this action
- Use `nsyte ci` and store only the resulting `nbunksec1...` credential as a GitHub Secret
- **DO NOT** commit signing credentials to source code
- Configure bunker with minimal permissions
- Consider pinning to specific `nsyte_version`
- Rotate `nbunksec` periodically
- Consider pinning to a specific `version`
- Rotate credentials periodically

## Resources
- [awesome-nsite](https://github.com/nostrver-se/awesome-nsite)
Expand Down
Loading
Loading