Skip to content

Commit

Permalink
feat: add web page to query artifacts (#105)
Browse files Browse the repository at this point in the history
* wip

* fix download urls

* feat: define web page to query artifacts registry

* commit apps folder

* fix build

* feat: define deploy web app to s3

* chore: delete apps/package.json

* chore: delete apps/web/.gitignore

* fix build script in deploy web app workflow

* chore: delete apps/web/src/assets

* chore: remove console.log

* feat: reset selected file on version select change

* refactor: extract options list in Component

* chore: format

* refactor: control selectedFile input

* fix: center body

* update css

* test: increase timeout

* Update .github/workflows/deploy-web-app.yaml

Co-authored-by: ntampakas <[email protected]>

---------

Co-authored-by: ntampakas <[email protected]>
  • Loading branch information
sripwoud and ntampakas authored Jun 26, 2024
1 parent fa3e322 commit ab082b4
Show file tree
Hide file tree
Showing 32 changed files with 1,557 additions and 36 deletions.
21 changes: 7 additions & 14 deletions .biome.jsonc
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"$schema": "https://biomejs.dev/schemas/1.7.3/schema.json",
"files": {
"ignore": [
"coverage/**",
"dist/**",
],
"ignore": ["coverage/**", "dist/**"],
},
"formatter": {
// use dprint instead
Expand All @@ -17,19 +14,15 @@
"overrides": [
{
"include": ["packages/cli/src/spinner.ts"],
"linter": {
"rules": {
"suspicious": { "noExplicitAny": "off" },
},
},
"linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } },
},
{
"include": ["packages/cli/src/commands/download/index.ts", "packages/cli/src/commands/generate/action.ts"],
"linter": {
"rules": {
"style": { "noParameterAssign": "off" },
},
},
"linter": { "rules": { "style": { "noParameterAssign": "off" } } },
},
{
"include": ["apps/web/src/main.tsx"],
"linter": { "rules": { "style": { "noNonNullAssertion": "off" } } },
},
],
}
56 changes: 56 additions & 0 deletions .github/workflows/deploy-web-app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Upload Artifacts
on:
push:
branches:
- main
paths: ['apps/web/**', '.github/workflows/deploy-web-app.yaml']

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0

- uses: actions/setup-node@v4

- uses: pnpm/action-setup@v4
with:
run_install: false

- shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- run: pnpm i --ignore-scripts

- uses: actions/cache@v4
with:
path: ${{env.STORE_PATH}}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store

- name: Build
run: pnpm --filter web build

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::490752553772:role/snark-artifacts-assume_role-slc
role-duration-seconds: 900
aws-region: us-west-2

- name: Upload index.html and assets to s3 bucket
run: |
aws s3 sync apps/web/dist s3://snark-artifacts/ --exclude "*" --include "index.html" --include "assets/*" --delete
12 changes: 12 additions & 0 deletions apps/web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Snark Artifacts Registry</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "web",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview"
},
"dependencies": {
"@octokit/rest": "^21.0.0",
"jotai": "^2.8.3",
"preact": "^10.22.0",
"react-query": "^3.39.3"
},
"devDependencies": {
"@preact/preset-vite": "^2.8.2",
"typescript": "^5.2.2",
"vite": "^5.3.1"
}
}
5 changes: 5 additions & 0 deletions apps/web/src/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#app {
max-width: 1280px;
padding: 2rem;
text-align: center;
}
15 changes: 15 additions & 0 deletions apps/web/src/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Footer, Header } from './components'
import { DownloadButton, FileSelect, ProjectSelect, VersionSelect } from './containers'

export const App = () => (
<>
<Header />
<div className='form'>
<ProjectSelect />
<VersionSelect />
<FileSelect />
<DownloadButton />
</div>
<Footer />
</>
)
16 changes: 16 additions & 0 deletions apps/web/src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { owner, repo } from '../constants'

export const Footer = () => (
<footer>
<p>
Copyright &copy;
<span>{' '}2024</span>
<span>{' '}PSE</span>
<a href={`https://github.com/${owner}/${repo}`}>
<span>
{' '}GitHub
</span>
</a>
</p>
</footer>
)
5 changes: 5 additions & 0 deletions apps/web/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const Header = () => (
<header>
<h1>Snark Artifacts Registry</h1>
</header>
)
3 changes: 3 additions & 0 deletions apps/web/src/components/Options.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const Options = ({ items }: { items: string[] }) => (
<>{items.map((item) => <option key={item} value={item}>{item}</option>)}</>
)
3 changes: 3 additions & 0 deletions apps/web/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { Footer } from './Footer'
export { Header } from './Header'
export { Options } from './Options'
5 changes: 5 additions & 0 deletions apps/web/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const artifacts = ['wasm', 'zkey']
export const owner = 'privacy-scaling-explorations'
export const repo = 'snark-artifacts'
export const projects = ['poseidon', 'semaphore', 'sempahore-identity']
export const cdnUrl = 'https://snark-artifacts.pse.dev'
13 changes: 13 additions & 0 deletions apps/web/src/containers/DownloadButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { cdnUrl } from '../constants'
import { useStore } from '../hooks'

export function DownloadButton() {
const { selectedFile, selectedProject, selectedVersion } = useStore()

const onClick = () => {
const url = `${cdnUrl}/${selectedProject}/${selectedVersion}/${selectedFile}`
window.location.href = url
}

return <button type='button' onClick={onClick} className='btn btn-primary' disabled={!selectedFile}>Download</button>
}
31 changes: 31 additions & 0 deletions apps/web/src/containers/FileSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { ChangeEvent } from 'react'
import { Options } from '../components'
import { useFiles, useStore } from '../hooks'

export function FileSelect() {
const { selectedFile, setSelectedFile } = useStore()
const { data: files, isLoading, isFetched, isSuccess, isError, error } = useFiles()
const onChange = (e: ChangeEvent<HTMLSelectElement>) => {
const file = e.target as HTMLSelectElement
setSelectedFile(file.value)
}

if (isLoading) return <div>Loading...</div>
if (!isFetched) return null
if (isError) return <div>{(error as Error).message}</div>
if (isSuccess) {
return (
<div>
<label htmlFor='file'>File</label>
<select id='file' onChange={onChange} value={selectedFile}>
<Options items={files} />
</select>
{
/* <label htmlFor='all-files' style={{ marginLeft: '1rem'}}>Download all</label>
<input id='all-files' type='checkbox' /> */
}
</div>
)
}
return null
}
24 changes: 24 additions & 0 deletions apps/web/src/containers/ProjectSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { ChangeEvent } from 'react'
import { Options } from '../components'
import { projects } from '../constants'
import { useStore } from '../hooks'

export function ProjectSelect() {
const { selectedProject, setSelectedProject, resetSelectedFile, resetSelectedVersion } = useStore()

const onChange = (e: ChangeEvent<HTMLSelectElement>) => {
resetSelectedFile()
resetSelectedVersion()
const target = e.target as HTMLSelectElement
setSelectedProject(target.value)
}

return (
<div>
<label htmlFor='project'>Project</label>
<select value={selectedProject} onChange={onChange} id='project'>
<Options items={projects} />
</select>
</div>
)
}
29 changes: 29 additions & 0 deletions apps/web/src/containers/VersionSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { ChangeEvent } from 'react'
import { Options } from '../components'
import { useStore, useVersions } from '../hooks'

export function VersionSelect() {
const { selectedVersion, setSelectedVersion, resetSelectedFile } = useStore()
const { data: versions, isSuccess, isFetched, isLoading, isError, error } = useVersions()

const onChange = (e: ChangeEvent<HTMLSelectElement>) => {
resetSelectedFile()
const target = e.target as HTMLSelectElement
setSelectedVersion(target.value)
}

if (isLoading) return <div>Loading...</div>
if (!isFetched) return null
if (isError) return <div>Error: {(error as Error).message}</div>
if (isSuccess) {
return (
<div>
<label htmlFor='version'>Version</label>
<select id='version' value={selectedVersion} onChange={onChange}>
<Options items={versions} />
</select>
</div>
)
}
return null
}
4 changes: 4 additions & 0 deletions apps/web/src/containers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './DownloadButton'
export * from './FileSelect'
export * from './ProjectSelect'
export * from './VersionSelect'
3 changes: 3 additions & 0 deletions apps/web/src/gh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Octokit } from '@octokit/rest'

export const gh = new Octokit({})
3 changes: 3 additions & 0 deletions apps/web/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './useFiles'
export * from './useStore'
export * from './useVersions'
26 changes: 26 additions & 0 deletions apps/web/src/hooks/useFiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useQuery } from 'react-query'
import { artifacts, owner, repo } from '../constants'
import { gh } from '../gh'
import { useStore } from '../hooks'

async function fetchFiles(version: string) {
const { data: { tree } } = await gh.git.getTree({ owner, repo, tree_sha: version, recursive: 'true' })
return tree.reduce((files, { path, type }) => {
if (type === 'blob' && path !== undefined)
files.push(path)
return files
}, [] as string[])
}

export function useFiles() {
const { selectedProject, selectedVersion } = useStore()
return useQuery({
enabled: selectedProject !== '' && selectedVersion !== '',
queryKey: ['files', selectedProject, selectedVersion],
queryFn: async () => fetchFiles(`@zk-kit/${selectedProject}-artifacts@${selectedVersion}`),
select: data => {
const regex = new RegExp(`^packages/${selectedProject}/.*\\.(${artifacts.join('|')})$`)
return data.filter(file => regex.test(file)).map(file => file.replace(`packages/${selectedProject}/`, ''))
},
})
}
22 changes: 22 additions & 0 deletions apps/web/src/hooks/useStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { atom, useAtom } from 'jotai'

const selectedFileAtom = atom('')
const selectedProjectAtom = atom('')
const selectedVersionAtom = atom('')

export const useStore = () => {
const [selectedFile, setSelectedFile] = useAtom(selectedFileAtom)
const [selectedProject, setSelectedProject] = useAtom(selectedProjectAtom)
const [selectedVersion, setSelectedVersion] = useAtom(selectedVersionAtom)

return {
selectedFile,
resetSelectedFile: () => setSelectedFile(''),
setSelectedFile,
selectedProject,
setSelectedProject,
selectedVersion,
resetSelectedVersion: () => setSelectedVersion(''),
setSelectedVersion,
}
}
21 changes: 21 additions & 0 deletions apps/web/src/hooks/useVersions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useQuery } from 'react-query'
import { owner, repo } from '../constants'
import { gh } from '../gh'
import { useStore } from './useStore'

async function queryFn() {
const { data: tags } = await gh.repos.listTags({ owner, repo })
return tags.map(tag => tag.name)
}

export function useVersions() {
const { selectedProject } = useStore()

return useQuery({
enabled: selectedProject !== '',
queryKey: ['versions', selectedProject],
queryFn,
select: (data) =>
data.filter(tag => tag.includes(`@zk-kit/${selectedProject}-artifacts@`)).map(tag => tag.split('@')[2]),
})
}
Loading

0 comments on commit ab082b4

Please sign in to comment.