Skip to content

Commit 1359388

Browse files
authored
feat: build next.js and push to ipfs action (#4)
1 parent 107f742 commit 1359388

File tree

6 files changed

+176
-1
lines changed

6 files changed

+176
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
.idea
1+
.idea
2+
.DS_Store

build-nextjs-app/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Build Next.js App action
2+
3+
This action builds and exports a Next.js app
4+
5+
## Inputs
6+
7+
## `node-version`
8+
9+
Node.js version
10+
11+
## `fa-token`
12+
13+
FontAwesome NPM Auth Token
14+
15+
## `export`
16+
17+
Whether to export the app or not
18+
19+
## Example usage
20+
21+
```yaml
22+
- name: Build and Export
23+
uses: aleph-im/aleph-github-actions/build@v1
24+
```

build-nextjs-app/action.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Build
2+
description: Build and export Next.js app
3+
4+
inputs:
5+
node-version:
6+
description: 'Node.js version'
7+
required: false
8+
default: 18
9+
fa-token:
10+
description: 'FontAwesome NPM Auth Token (optional)'
11+
required: false
12+
default: ''
13+
export:
14+
description: 'Whether to export the app as a static site or not'
15+
required: false
16+
default: true
17+
18+
runs:
19+
using: 'composite'
20+
steps:
21+
- name: Setup Node.js
22+
uses: actions/setup-node@v3
23+
with:
24+
node-version: ${{ inputs.node-version }}
25+
cache: npm
26+
27+
- name: Install dependencies
28+
shell: bash
29+
env:
30+
FONTAWESOME_NPM_AUTH_TOKEN: ${{ inputs.fa-token }}
31+
run: npm ci
32+
33+
- name: Cache
34+
uses: actions/cache@v4
35+
with:
36+
path: .next/cache
37+
# Generate a new cache whenever packages or next config changes.
38+
key: ${{ runner.os }}-next-build-${{ hashFiles('**/package-lock.json','**/next.config.js') }}
39+
restore-keys: |
40+
${{ runner.os }}-next-build-
41+
42+
- name: Build and export
43+
shell: bash
44+
env:
45+
NEXTJS_EXPORT: ${{ inputs.export }}
46+
run: npm run build

push-to-ipfs/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Push to IPFS action
2+
3+
This action performs a pin to Aleph IPFS
4+
5+
## Inputs
6+
7+
## `upload-dir`
8+
9+
**Required** Directory to upload
10+
11+
## Outputs
12+
13+
## `cid`
14+
15+
Generated IPFS CID
16+
17+
## Example usage
18+
19+
```yaml
20+
- name: Push to IPFS
21+
uses: aleph-im/aleph-github-actions/push-to-ipfs@v1
22+
with:
23+
upload-dir: out
24+
```

push-to-ipfs/action.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Push to IPFS
2+
description: Push directory to IPFS
3+
4+
inputs:
5+
upload-dir:
6+
description: 'Directory to upload'
7+
required: true
8+
9+
runs:
10+
using: 'composite'
11+
steps:
12+
- name: Push to IPFS
13+
id: push_to_ipfs
14+
shell: bash
15+
run: |
16+
pip install 'aioipfs>=0.6.2'
17+
CID=$(python3 ${{ github.action_path }}/scripts/push_on_ipfs.py "${{ inputs.upload-dir }}")
18+
echo "CID: $CID" >> $GITHUB_STEP_SUMMARY
19+
echo "cid=$CID" >> $GITHUB_OUTPUT
20+
outputs:
21+
cid:
22+
description: 'IPFS CID'
23+
value: ${{ steps.push_to_ipfs.outputs.cid }}

push-to-ipfs/scripts/push_on_ipfs.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
This script uploads the build SPA to IPFS.
5+
It does not ping it or do anything else yet, so the result can only be accessed
6+
as long as the files are not garbage collected.
7+
Requires: 'aioipfs>=0.6.2'
8+
"""
9+
10+
import asyncio
11+
import logging
12+
from pathlib import Path
13+
from typing import NewType
14+
15+
import aioipfs
16+
17+
logger = logging.getLogger(__file__)
18+
19+
Multiaddr = NewType("Multiaddr", str)
20+
CID = NewType("CID", str)
21+
22+
23+
def raise_no_cid():
24+
raise ValueError("Could not obtain a CID")
25+
26+
27+
async def upload_site(files: list[Path], multiaddr: Multiaddr) -> CID:
28+
client = aioipfs.AsyncIPFS(maddr=multiaddr)
29+
30+
try:
31+
cid = None
32+
async for added_file in client.add(*files, recursive=True):
33+
logger.debug(
34+
f"Uploaded file {added_file['Name']} with CID: {added_file['Hash']}"
35+
)
36+
cid = added_file["Hash"]
37+
# The last CID is the CID of the directory uploaded
38+
return cid or raise_no_cid()
39+
finally:
40+
await client.close()
41+
42+
43+
async def publish_site(multiaddr: Multiaddr) -> CID:
44+
path = Path(__file__).parent / "../out"
45+
if not path.is_dir():
46+
raise NotADirectoryError(f"No such directory: {path}")
47+
cid = await upload_site(files=[path], multiaddr=multiaddr)
48+
return cid
49+
50+
51+
def main():
52+
print(asyncio.run(publish_site(Multiaddr("/dns6/ipfs-2.aleph.im/tcp/443/https"))))
53+
54+
55+
if __name__ == "__main__":
56+
logging.basicConfig(level=logging.INFO)
57+
main()

0 commit comments

Comments
 (0)