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

ci(dev-cli): use ardrive to publish binaries #253 #255

Merged
merged 1 commit into from
Dec 21, 2023
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
137 changes: 86 additions & 51 deletions .github/workflows/dev-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ jobs:
VER=`npm --version`; echo "npm ver: $VER"
VER=`deno --version`; echo "deno ver: $VER"

- name: 🔬 Decode Wallet JSON File
uses: timheuer/base64-to-file@v1
id: wallet_file
with:
fileName: wallet.json
encodedString: ${{ secrets.CI_WALLET }}

# The version in the manifest is used to set the version
# displayed for the CI. So we need to update version,
# prior to building the binaries
Expand All @@ -133,52 +140,69 @@ jobs:
env:
CI: true

- name: Install Irys Client
- name: Install ArDrive CLI
run: |
npm i -g @irys/[email protected]
npm i -g ardrive-cli@2

- name: 💾 Publish Binaries to Arweave
id: publish_binaries
# Irys may fail to deploy the binaries to Arweave for a number of reasons
#
# So before attempting to extract the transaction id from the output
# We first check to make sure the success message is output
#
# If the deploy was successful, We output text to stdout, the final line containing
# the url of the transaction. We only need the transaction id
#
# So we tail the output and strip the last part of the printed url
# which should be the transaction id

#
# Use the ArDrive CLI to:
# - create a new folder in the ao CLI Artifacts Drive
# - upload binaries to that folder
# - create a manifest of the folder
# We also add additional tags in order to mint $U
#
run: |
irys balance ${CI_WALLET_ADDRESS} \
-h ${IRYS_NODE} \
-t arweave

irys price $(du -b "${BINARIES_OUTPUT_DIR}" | cut -f1) \
-h ${IRYS_NODE} \
-t arweave

IRYS_RESULT=$(deno task deploy-binaries)

echo "${IRYS_RESULT}"
if [[ -z $(echo "${IRYS_RESULT}" | awk '/^Uploaded to https:\/\/arweave.net\//') ]]; then
echo "Binaries were not successfully deployed to Irys! See above logs."
exit 1
fi

TRANSACTION_ID=$(\
echo "${IRYS_RESULT}" \
| tail -1 \
| awk -F/ '{print $NF}'
echo "Creating folder for binaries on ArDrive..."

ARDRIVE_FOLDER_RESULT=$(\
ardrive create-folder \
--turbo \
--parent-folder-id "${ARDRIVE_FOLDER_ID}" \
--folder-name "${VERSION}" \
-w "${WALLET}"
)

echo "${ARDRIVE_FOLDER_RESULT}"

FOLDER_ID=$(\
echo "${ARDRIVE_FOLDER_RESULT}" \
| jq -r '.created[0].entityId'
)

echo "Uploading Binaries..."

ardrive upload-file \
--turbo \
--parent-folder-id "${FOLDER_ID}" \
--local-paths "${BINARIES_OUTPUT_DIR}"/*.zip \
-w "${WALLET}"

echo "Generating Manifest..."

ARDRIVE_MANIFEST_RESULTS=$(\
ardrive create-manifest \
--turbo \
-f "${FOLDER_ID}" \
-w "${WALLET}"
)
echo "tx_id=${TRANSACTION_ID}" >> $GITHUB_OUTPUT

echo "${ARDRIVE_MANIFEST_RESULTS}"

BINARIES_TRANSACTION_ID=$(\
echo "${ARDRIVE_MANIFEST_RESULTS}" \
| jq -r '.created[0].dataTxId'
)

echo "folder_id=${FOLDER_ID}" >> $GITHUB_OUTPUT
echo "tx_id=${BINARIES_TRANSACTION_ID}" >> $GITHUB_OUTPUT
env:
CI_WALLET_ADDRESS: ${{ secrets.CI_WALLET_ADDRESS }}
WALLET: ${{ steps.wallet_file.outputs.filePath }}
VERSION: ${{ steps.version.outputs.version }}
BINARIES_OUTPUT_DIR: ${{ steps.build_binaries.outputs.binaries_output_dir }}
IRYS_NODE: https://node2.irys.xyz
CI_WALLET: ${{ secrets.CI_WALLET }}
ARDRIVE_FOLDER_ID: ${{ secrets.CLI_ARDRIVE_FOLDER_ID }}

- name: 🛠 Build Install Script
id: build_install_script
Expand All @@ -189,6 +213,11 @@ jobs:
CI: true
BINARIES_TRANSACTION_ID: ${{ steps.publish_binaries.outputs.tx_id }}

#
# Use the ArDrive CLI to:
# - upload the install script to the same folder
#
# Then finally trigger script to update ArNS for install-ao
- name: 🛠 Publish Install Script to Arweave
id: publish_install
# We output text to stdout, the final line containing
Expand All @@ -197,23 +226,29 @@ jobs:
# So we tail the output and strip the last part of the printed url
# which should be the transaction id
run: |
IRYS_RESULT=$(deno task deploy-install-script)

echo "${IRYS_RESULT}"
if [[ -z $(echo "${IRYS_RESULT}" | awk '/^Uploaded to https:\/\/arweave.net\//') ]]; then
echo "Binaries were not successfully deployed to Irys! See above logs."
exit 1
fi

TRANSACTION_ID=$(\
echo "${IRYS_RESULT}" \
| tail -1 \
| awk -F/ '{print $NF}'
echo "Uploading Install Script..."

ARDRIVE_FILE_RESULTS=$(\
ardrive upload-file \
--turbo \
--parent-folder-id "${FOLDER_ID}" \
--local-path "${INSTALL_SCRIPT}" \
-w "${WALLET}"
)
echo "tx_id=${TRANSACTION_ID}" >> $GITHUB_OUTPUT

echo "${ARDRIVE_FILE_RESULTS}"

INSTALL_TRANSACTION_ID=$(\
echo "${ARDRIVE_FILE_RESULTS}" \
| jq -r '.created[0].dataTxId'
)

INSTALL_SCRIPT_ID="${INSTALL_TRANSACTION_ID}" deno task arns-install-script

echo "tx_id=${INSTALL_TRANSACTION_ID}" >> $GITHUB_OUTPUT
env:
IRYS_NODE: https://node2.irys.xyz
CI_WALLET: ${{ secrets.CI_WALLET }}
WALLET: ${{ steps.wallet_file.outputs.filePath }}
FOLDER_ID: ${{ steps.publish_binaries.outputs.folder_id }}
INSTALL_SCRIPT: ${{ steps.build_install_script.outputs.install_script }}

- name: 🤓 Set Git User
Expand Down
3 changes: 1 addition & 2 deletions dev-cli/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
"tasks": {
"cache": "deno cache --lock=deno.lock --lock-write ./src/mod.js",
"build-binaries": "./tools/build.sh",
"deploy-binaries": "ACTION=UPLOAD_BINARIES node tools/deploy/index.js",
"build-install-script": "deno run -A tools/create-install-script.js",
"deploy-install-script": "ACTION=UPLOAD_INSTALL_SCRIPT node tools/deploy/index.js",
"arns-install-script": "ACTION=UPDATE_ARNS node tools/deploy/index.js",
"bump": "deno run -A tools/update-version.js",
"test": "echo 'NOT IMPLEMENTED'",
"tx-mappings": "deno run -A tools/update-tx-mappings.js",
Expand Down
61 changes: 14 additions & 47 deletions dev-cli/tools/deploy/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Buffer } from 'node:buffer'
import { readFileSync } from 'node:fs'

import Irys from '@irys/sdk'
import { WarpFactory, defaultCacheOptions } from 'warp-contracts'
import Arweave from 'arweave'
import { z } from 'zod'
Expand All @@ -14,47 +13,22 @@ function env (key) {
return res.data
}

/**
* The wallet is encoded in base64, so we must load the base64
* into a buffer, then parse it to a utf-8 string, that can then
* be further parsed into the JSON JWK Interface
*/
function parseWallet (wallet64) {
return JSON.parse(Buffer.from(wallet64, 'base64').toString('utf-8'))
}

/**
* Add U Tags in order to Mint U as part of CI
*/
const U_TAGS = [
{ name: 'App-Name', value: 'SmartWeaveAction' },
{ name: 'App-Version', value: '0.3.0' },
{ name: 'Input', value: JSON.stringify({ function: 'mint' }) },
{ name: 'Contract', value: 'KTzTXT_ANmF84fWEKHzWURD1LWd9QaFR9yfYUwH2Lxw' }
]
// const U_TAGS = [
// { name: 'App-Name', value: 'SmartWeaveAction' },
// { name: 'App-Version', value: '0.3.0' },
// { name: 'Input', value: JSON.stringify({ function: 'mint' }) },
// { name: 'Contract', value: 'KTzTXT_ANmF84fWEKHzWURD1LWd9QaFR9yfYUwH2Lxw' }
// ]

const actions = {
async UPLOAD_BINARIES () {
const DEPLOY_FOLDER = env('BINARIES_OUTPUT_DIR')
const IRYS_NODE = env('IRYS_NODE')
const WALLET_64 = env('CI_WALLET')
async UPDATE_ARNS () {
const WALLET = env('WALLET')
const INSTALL_SCRIPT_ID = env('INSTALL_SCRIPT_ID')

const jwk = parseWallet(WALLET_64)
const irys = new Irys({ url: IRYS_NODE, token: 'arweave', key: jwk })

const res = await irys.uploadFolder(DEPLOY_FOLDER, {
manifestTags: U_TAGS,
itemOptions: { tags: U_TAGS }
})

return res.id
},
async UPLOAD_INSTALL_SCRIPT () {
const IRYS_NODE = env('IRYS_NODE')
const WALLET_64 = env('CI_WALLET')
const INSTALL_SCRIPT = env('INSTALL_SCRIPT')

const jwk = parseWallet(WALLET_64)
const jwk = JSON.parse(readFileSync(WALLET))

/**
* The install_ao ANT Contract
Expand All @@ -63,30 +37,23 @@ const actions = {
const ANT = 'uOf4TMgQxdaSXgcZ778PZR13UQPKJoZVK2ZvLAE90Xg'

const arweave = Arweave.init({ host: 'arweave.net', port: 443, protocol: 'https' })
const irys = new Irys({ url: IRYS_NODE, token: 'arweave', key: jwk })
const warp = WarpFactory.custom(arweave, defaultCacheOptions, 'mainnet').useArweaveGateway().build()

// Upload the install script
const res = await irys.uploadFile(INSTALL_SCRIPT, { tags: U_TAGS })

// Update the ao ANT Contract to point to the new install script
const aoAntContract = warp.contract(ANT).connect(jwk)
const antUpdate = await aoAntContract.writeInteraction({
function: 'setRecord',
subDomain: 'install',
transactionId: res.id
transactionId: INSTALL_SCRIPT_ID
})

console.log('Updated ao ANT record', antUpdate.interactionTx)

return res.id
return INSTALL_SCRIPT_ID
}
}

const ACTION = env('ACTION')
if (!actions[ACTION]) throw new Error(`'${ACTION}' is not a valid action`)

// For capturing in std-out
actions[ACTION]().then(id => {
console.log(`Uploaded to https://arweave.net/${id}`)
}).catch(console.error)
actions[ACTION]().catch(console.error)