Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: update to work with w3up api #89

Merged
merged 13 commits into from
Jan 17, 2024
Merged
1 change: 0 additions & 1 deletion .gitattributes

This file was deleted.

9 changes: 0 additions & 9 deletions .github/dependabot.yml

This file was deleted.

54 changes: 36 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,45 @@ on:
- 'releases/*'

jobs:
test:
run-action:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v4

- name: run 1 - upload
uses: ./
id: run1
with:
node-version: 16
- uses: bahmutov/npm-install@v1
- run: npm run lint
- run: npm test
env:
INPUT_WEB3_TOKEN: ${{ secrets.WEB3_STORAGE_TOKEN }}
path_to_add: 'test/fixtures'
proof: ${{ secrets.W3_PROOF }}
secret_key: ${{ secrets.W3_PRINCIPAL }}

run-action:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./
- name: test run 1 output
run: echo "unexpected output cid ${{ steps.run1.outputs.cid }}" && exit 1
if: ${{ steps.run1.outputs.cid != 'bafybeifpw7nrh374rzfcxpaw3bkp6fr7djmujg5wvib6ma7i7n76t3k53q' }}

- name: run 2 - upload (wrap=false)
uses: ./
id: run2
with:
wrap: false
path_to_add: 'test/fixtures'
proof: ${{ secrets.W3_PROOF }}
secret_key: ${{ secrets.W3_PRINCIPAL }}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: consider using same names here instead of secret key and principal?


- name: test run 2 output
run: echo "unexpected output cid ${{ steps.run2.outputs.cid }}" && exit 1
if: ${{ steps.run2.outputs.cid != 'bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy' }}

- name: run 3 - upload (hidden=true)
uses: ./
id: run3
with:
web3_api: 'https://api-staging.web3.storage'
web3_token: ${{ secrets.WEB3_STORAGE_TOKEN }}
hidden: true
path_to_add: 'test/fixtures'
# test non default option
include_hidden: true
proof: ${{ secrets.W3_PROOF }}
secret_key: ${{ secrets.W3_PRINCIPAL }}

- name: test run 3 output
run: echo "unexpected output cid ${{ steps.run3.outputs.cid }}" && exit 1
if: ${{ steps.run3.outputs.cid != 'bafybeiht4hxkewkiqwa3rbw6bnlom2s7wajkbspsgjgn6wojioii4rh77y' }}
87 changes: 58 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,62 +1,94 @@
<h1 align="center">⁂<br/>web3.storage</h1>
<p align="center">Add a directory to web3.storage from an Action, and output it's IPFS Content ID.</p>
# add-to-web3

! v3 of this action will work with the new w3up api once https://github.com/web3-storage/add-to-web3/issues/87 lands.
Upload files to [web3.storage](https://web3.storage) from a Github Action, and output the IPFS Content ID.

## Example usage
A lightweight wrapper around [w3cli](https://github.com/web3-storage/w3cli). As a [composite](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action) github action all it does is configure and call the cli for you. See the steps in [./action.yml](./action.yml).

## Usage

```yaml
uses: web3-storage/add-to-web3@v2
id: web3
uses: web3-storage/add-to-web3@v3
id: w3up
with:
web3_token: ${{ secrets.WEB3_STORAGE_TOKEN }}
path_to_add: 'dist'
proof: ${{ secrets.W3_PROOF }}
secret_key: ${{ secrets.W3_PRINCIPAL }}

# use the outputs in subsequent steps
# "bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am"
- run: echo ${{ steps.web3.outputs.cid }}
- run: echo ${{ steps.w3up.outputs.cid }}

# "https://bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am.ipfs.w3s.link"
- run: echo ${{ steps.w3up.outputs.url }}
```

Use [w3cli] to generate a `secret_key` and `proof` to allow this action to upload to a space on.

# "https://dweb.link/ipfs/bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am"
- run: echo ${{ steps.web3.outputs.url }}
Install it from npm and login as described here https://web3.storage/docs/quickstart/ then:

```shell
# create a signing key for CI.
# Use the `did` in the input to the next command.
# Use `key` as your `secret_key` for add_to_web3.
$ w3 key create --json
{
"did": "did:key:z6Mk...",
"key": "MgCaT7Se2QX9..."
}

# create a base64 encoded UCAN `proof`
# It delegates store and upload permissions to the `did` we created above.
$ w3 delegation create did:key:z6Mk... -c 'store/add' -c 'upload/add' --base64
mAYIEAP8OEaJlcm9vdHOAZ3ZlcnNpb24BwwUBcRIg+oHTbzShh1WzBo9ISkonCW+KAcy/+zW8Zb...
```

- Use the `key` value from the output of `w3 key create --json` as the `secret_key` for this action.
- Use the `did value from that command as the audience for `w3 delegation create <audience>` shown above.
- Use the output of `w3 delegation create <audience>` as the `proof` for this action.

Keep the `secret_key` safe. Save it as a secret on your repo. The `proof` delegates permission from your account to that key to upload to your space. The `proof` can only be used by an agent that holds the `secret_key`.

## Inputs

### `path_to_add`

**Required** The path the root directory of your static website or other content that you want to publish to IPFS.

### `web3_token`
### `secret_key`

**Required** API token for web3.storage
**Required** The base64 encoded key to use to sign UCAN invocations to web3.storage.

<details>
<summary>Show advanced options: <code>wrap_with_directory</code>, <code>include_hidden</code>, <code>web3_api</code></summary>

### `wrap_with_directory`
Create one using `w3 key create`. See: https://github.com/web3-storage/w3cli#w3_principal

_Default_ `false`
### `proof`

Should the `path_to_add` be wrapped in a diretory when creating the IPFS DAG. For most folks using this action the default of `false` is fine.
**Required** A base64 encoded UCAN delegating capabilities the signing key above.

This is the opposite of the default that web3.storage uses, as this action is commonly used to add a directory that contains a static website to IPFS. In that case you want the path_to_add to become the root cid so you can host your site at `https://<cid>.ipfs.dweb.link` rather than `https://<cid>.ipfs.dweb.link/<path_to_add>`.
Create a proof using w3cli, delegating `store/add' and `upload/add`

If you do want to capture the `path_to_add` path itself in the IPFS DAG then you want to set `wrap_with_directory:true`.
```shell
$ AUDIENCE_DID="<the DID for secret_key created by `w3 key create`>"
$ w3 delegation create $AUDIENCE_DID -c 'store/add' -c 'upload/add' --base64`
```

see: https://web3.storage/docs/reference/js-client-library#parameters
<details>
<summary>Show advanced options: <code>hidden</code>, <code>wrap</code></summary>

### `include_hidden`
### `hidden`

_Default_ `false`

Should hidden files prefixed with a `.` be included when found in the `path_to_add`

see: https://github.com/web3-storage/files-from-path#filesfrompath
see: See: https://github.com/web3-storage/w3cli#w3-up-path-path

### `wrap`

### `web3_api`
_Default_ `true`

_Default_ `https://api.web3.storage`
If `path_to_add` points to a file it will be wrapped in a directory to preserve the filename. To disable that set wrap: "true".

Useful for testing against staging deployments by setting to the api origin of your choice.
See: https://github.com/web3-storage/w3cli#w3-up-path-path

</details>

Expand All @@ -72,11 +104,8 @@ e.g. `bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am`
The IPFS gateway URL for the directory
e.g. `https://dweb.link/ipfs/bafkreicysg23kiwv34eg2d7qweipxwosdo2py4ldv42nbauguluen5v6am`


## Contibuting

💌 Considerate contributions welcome!

The `dist` folder is commited to the repo as is the curious cultural norm with JS actions, as the repo is the delivery mechanism, so to spare some cycles for the user users, all the deps are bundled into a single /dist/index.js monolith.

<h3 align="center"><a href="https://web3.storage">⁂</a></h3>
64 changes: 49 additions & 15 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,64 @@ author: olizilla
branding:
icon: 'box'
color: 'white'

inputs:
path_to_add:
description: 'Directory path to add to IPFS'
required: true
include_hidden:
description: 'Include hidden files'
required: false
default: 'false'
web3_token:
description: 'API token for web3.storage'

secret_key:
description: 'The base64 encoded key to use to sign UCAN invocations. Create one using `w3 key create`. See: https://github.com/web3-storage/w3cli#w3_principal'
required: true
web3_api:
description: 'API URL'
required: false
default: 'https://api.web3.storage'
wrap_with_directory:
description: 'Boolean. Default: `false`. Should the path_to_add be wrapped in a diretory when creating the IPFS DAG. For most folks using this, the default of `false` is fine. If you want to add a single file and preserve the filename in the IPFS DAG you may want to set it to `true`.'

proof:
description: 'A base64 encoded UCAN delegating capabilities the secret signing key above. Create using `w3 delegation create --base64`'
required: true

hidden:
description: 'Include paths that start with "."'
required: false
default: 'false'

wrap:
description: 'If `path_to_add` points to a file it will be wrapped in a directory to preserve the filename. To disable that set wrap: "false"'
required: false
default: 'true'

outputs:
cid:
description: 'The IPFS Content ID for the directory'
description: 'The IPFS Content ID for path_to_add'
value: ${{ steps.get_cid.outputs.cid }}

url:
description: 'The IPFS Gateway URL'
value: ${{ steps.get_url.outputs.url }}

runs:
using: 'node16'
main: 'dist/index.js'
using: "composite"
steps:
- run: npm install -g @web3-storage/w3cli
shell: bash

- run: w3 space add ${{ inputs.proof }}
env:
W3_PRINCIPAL: ${{ inputs.secret_key }}
shell: bash

- run: w3 up ${{ inputs.path_to_add }} --json --hidden=${{ inputs.hidden }} --wrap=${{ inputs.wrap }} | tee ./w3_up_output.json
env:
W3_PRINCIPAL: ${{ inputs.secret_key }}
shell: bash

# expect `./w3_up_output.json` to contain "{ "root": { "/": "bafy..." }}
- name: fail if no CID in response
run: jq --exit-status --raw-output '.root."/"' ./w3_up_output.json
shell: bash

- id: get_cid
run: echo "cid=$(jq --exit-status --raw-output '.root."/"' ./w3_up_output.json)" >> "$GITHUB_OUTPUT"
shell: bash

- id: get_url
run: echo "url=https://${{ steps.get_cid.outputs.cid }}.ipfs.w3s.link" >> "$GITHUB_OUTPUT"
shell: bash
Loading