diff --git a/CLAUDE.md b/CLAUDE.md index 2680b1abb..66833652b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -77,6 +77,44 @@ Each package has its own scripts: - **Presets** - Different configurations of the same package (default is "main") - **cannon-std** - Foundry library for accessing deployment data in tests via `vm.getAddress()` +### Cannonfile Syntax Changes +**IMPORTANT**: When creating new cannonfiles, use the modern syntax for both variables and action steps: + +#### Variable Syntax +- **Deprecated `[setting.]` syntax**: `[setting.actual_setting_name]` where the section name itself was the setting +- **Current `[var.]` syntax**: `[var.section_label]` where the section name is just a label, and inside you define key-value pairs + +Example of correct `[var.]` syntax: +```toml +[var.protocol_config] +min_deposit_amount = "100000000000000000000" +protocol_fee_percentage = "250" +admin_address = "0x1234..." +``` + +Variables are still referenced using the same template syntax: `<%= settings.min_deposit_amount %>`, `<%= settings.protocol_fee_percentage %>`, etc. + +#### Action Step Syntax +The following action steps have been renamed (functionality remains identical): + +- **`[contract.]` → `[deploy.]`**: Deploy smart contracts +- **`[provision.]` → `[clone.]`**: Clone/provision packages from the registry +- **`[import.]` → `[pull.]`**: Pull external package data + +Example of modern action syntax: +```toml +[deploy.MyContract] +artifact = "MyContract" +args = ["<%= settings.admin_address %>"] + +[clone.oracle_manager] +source = "oracle-manager:1.0.0" +target = "oracle-manager:1.0.0@main" + +[pull.external_data] +source = "external-package:1.0.0" +``` + ### Workspace Structure ``` packages/ diff --git a/packages/website/guides/deployments-repo.mdx b/packages/website/guides/deployments-repo.mdx new file mode 100644 index 000000000..b71cf52f2 --- /dev/null +++ b/packages/website/guides/deployments-repo.mdx @@ -0,0 +1,419 @@ +--- +title: Create a Deployments Repository +description: Learn how to create and structure a dedicated deployments repository for managing protocol deployments with Cannon and GitOps workflows. +after: + url: "queue-with-gitops" + title: "Queue with GitOps" + description: "Learn how to use the Queue with GitOps functionality on the Cannon website." +--- + +## Create a Deployments Repository + +A deployments repository is a dedicated Git repository that contains only your Cannon deployment configurations, separate from your main smart contract codebase. This approach enables [GitOps](https://about.gitlab.com/topics/gitops/) workflows for teams that want to keep their smart contract source code private while maintaining transparent and collaborative deployment processes. + + + When to use a deployments repository + Consider using a deployments repository when you have private smart contract repositories but want to use the Cannon website's GitOps functionality, or when you want to separate deployment concerns from development workflows. + + +### Benefits of a Deployments Repository + +Using a dedicated deployments repository provides several advantages: + +- **Separation of Concerns**: Isolate deployment configurations from development workflows +- **Team Collaboration**: Allow engineers who work on deployments to work independently from contract developers +- **GitOps Integration**: Enable GitOps workflows +- **Audit Trail**: Maintain a clear history of all deployment activities and configurations +- **Privacy**: Have the option to keep your smart contract source code private while maintaining transparent deployments + +### Real-World Example: Synthetix Deployments + +The [Synthetix deployments repository](https://github.com/synthetixio/synthetix-deployments) is an excellent example of this pattern in practice. It demonstrates how a complex protocol with multiple networks, markets, and governance components can be managed entirely through a deployments repository. + +[Screenshot placeholder: Synthetix deployments repository structure on GitHub] + +### Repository Structure + +Based on the Synthetix model, here's an example structure for a deployments repository: + +``` +protocol-deployments/ +├── README.md +├── package.json +├── omnibus-mainnet.toml # Main network deployment +├── omnibus-sepolia.toml # Testnet deployment +├── omnibus-arbitrum-mainnet.toml # L2 deployments +├── omnibus-base-mainnet.toml +├── tomls/ # Modular configuration files +│ ├── settings.toml # Global settings +│ ├── core.toml # Core system deployment +│ ├── permissions.toml # Access control configurations +│ ├── collaterals/ # Collateral configurations +│ │ ├── weth.toml +│ │ ├── wsteth.toml +│ │ └── usdc.toml +│ ├── markets/ # Market-specific configs +│ │ ├── spot-factory.toml +│ │ └── perps.toml +│ ├── oracles/ # Oracle configurations +│ │ ├── chainlink.toml +│ │ └── pyth.toml +│ └── omnibus-mainnet/ # Network-specific overrides +│ ├── governance/ +│ ├── pools/ +│ └── overrides.toml +├── scripts/ # Utility scripts +│ ├── deploy.sh +│ └── verify.sh +└── e2e/ # End-to-end testing + └── tests/ +``` + +### Setting Up Your Deployments Repository + +#### Step 1: Create the Repository Structure + +1. **Initialize the repository**: + ```bash + mkdir protocol-deployments + cd protocol-deployments + git init + ``` + +2. **Set up package.json** with Cannon CLI and build scripts: + ```json + { + "name": "protocol-deployments", + "version": "1.0.0", + "private": true, + "scripts": { + "anvil:mainnet": "anvil --chain-id 1 --fork-url $MAINNET_RPC_URL", + "start:mainnet": "cannon build omnibus-mainnet.toml --keep-alive --dry-run --upgrade-from my-protocol:latest@main", + "build:mainnet": "cannon build omnibus-mainnet.toml --dry-run", + "test:mainnet": "mocha ./e2e/tests/omnibus-mainnet.toml/**/*.e2e.js", + "deploy:mainnet": "cannon build omnibus-mainnet.toml --private-key $PRIVATE_KEY", + "verify:mainnet": "cannon verify my-protocol@main --chain-id 1", + "publish:mainnet": "cannon publish my-protocol@main --chain-id 1" + }, + "devDependencies": { + "@usecannon/builder": "latest", + "@usecannon/cli": "latest", + "mocha": "^10.0.0", + "ethers": "^5.7.2" + } + } + ``` + +3. **Install dependencies**: + ```bash + yarn install + # Configure Cannon settings + yarn cannon setup + ``` + +[Screenshot placeholder: Package.json configuration and yarn install process] + +#### Step 2: Create Modular Configuration Files + +The key to maintainable deployments is breaking your configuration into modular files. You can place individual build steps in a TOML file: + +##### Global Settings (`tomls/settings.toml`) +```toml +[var.protocol_config] +min_deposit_amount = "100000000000000000000" # 100 tokens in wei +protocol_fee_percentage = "250" # 2.5% in basis points +withdrawal_delay = "86400" # 24 hours in seconds + +[invoke.setMinimumDeposit] +target = ["contracts.Protocol"] +fromCall.func = "owner" +func = "setMinimumDeposit" +args = ["<%= settings.min_deposit_amount %>"] + +[invoke.setProtocolFee] +target = ["contracts.Protocol"] +fromCall.func = "owner" +func = "setProtocolFee" +args = ["<%= settings.protocol_fee_percentage %>"] + +[invoke.setWithdrawalDelay] +target = ["contracts.Protocol"] +fromCall.func = "owner" +func = "setWithdrawalDelay" +args = ["<%= settings.withdrawal_delay %>"] +``` + +##### Core System (`tomls/core.toml`) +```toml +[var.system_config] +core_package = "my-protocol-core:1.0.0" +oracle_package = "oracle-manager:2.1.0" +owner_address = "" +target_preset = "main" +deployment_salt = "my-protocol" + +[clone.oracle_manager] +source = "<%= settings.oracle_package %>" +target = "<%= settings.oracle_package %>" +options.salt = "<%= settings.deployment_salt %>-oracle" +options.owner = "<%= settings.owner_address %>" + +[provision.system] +source = "<%= settings.core_package %>" +target = "<%= settings.core_package %>@<%= settings.target_preset %>" +options.owner = "<%= settings.owner_address %>" +options.salt = "<%= settings.deployment_salt %>" +``` + +##### Collateral Configuration (`tomls/collaterals/weth.toml`) +```toml +[var.weth_config] +token_address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # WETH mainnet +liquidation_reward = "<%= parseEther('0.01') %>" +issuance_ratio = "<%= parseEther('1.25') %>" +liquidation_ratio = "<%= parseEther('1.05') %>" +min_delegation = "<%= parseEther('1') %>" + +[invoke.configureWethCollateral] +target = ["contracts.Protocol"] +fromCall.func = "owner" +func = "configureCollateral" +args = [ + { + tokenAddress = "<%= settings.token_address %>", + oracleNodeId = "<%= extras.weth_oracle_id %>", + issuanceRatioD18 = "<%= settings.issuance_ratio %>", + liquidationRatioD18 = "<%= settings.liquidation_ratio %>", + liquidationRewardD18 = "<%= settings.liquidation_reward %>", + minDelegationD18 = "<%= settings.min_delegation %>", + depositingEnabled = true + }, +] +``` + +[Screenshot placeholder: Modular TOML file structure in file explorer] + +#### Step 3: Create Network-Specific Omnibus Files + +Now that you have created modular deployments, We can use `include` to pull components into our comprehensive deployment. + +Each network gets its own omnibus file that includes the relevant modules: + +##### Mainnet (`omnibus-mainnet.toml`) +```toml +name = "my-protocol" +version = "0.1.0" +description = "My Protocol full system deployment on Mainnet" +deployers = [ + "0x742d35Cc6634C0532925a3b8D4956AF55e86dB31", # Deployer 1 (EOA, for example) + "0x1234567890123456789012345678901234567890", # Deployer 2 (Safe, for example) +] +include = [ + "tomls/settings.toml", + "tomls/core.toml", + "tomls/permissions.toml", + "tomls/oracles/chainlink.toml", + "tomls/collaterals/weth.toml", + "tomls/collaterals/usdc.toml", + "tomls/markets/spot-factory.toml", + "tomls/omnibus-mainnet/overrides.toml", +] + +[var.packages] +core_package = "my-protocol-core:2.1.0" +oracle_package = "oracle-manager:3.10.1" +spot_market_package = "spot-market:1.5.0" + +[var.mainnet_config] +owner_address = "0x742d35Cc6634C0532925a3b8D4956AF55e86dB31" +deployment_salt = "my-protocol-mainnet" +``` + +##### Testnet (`omnibus-sepolia.toml`) +```toml +name = "my-protocol" +version = "2.1.0-sepolia" +description = "My Protocol testnet deployment" +include = [ + "tomls/settings.toml", + "tomls/core.toml", + "tomls/permissions.toml", + # Reduced configuration for testing + "tomls/collaterals/weth.toml", +] + +# Testnet-specific package versions (can be different/newer) +[var.packages] +core_package = "my-protocol-core:2.1.0-alpha" +oracle_package = "oracle-manager:3.10.1" + +[var.sepolia_config] +owner_address = "0x1234567890123456789012345678901234567890" +deployment_salt = "my-protocol-sepolia" +``` + +[Screenshot placeholder: Network-specific omnibus files showing includes and settings] + +#### Step 4: Set Up Testing Infrastructure + +Add end-to-end testing capabilities: + +```bash +mkdir -p e2e/tests/omnibus-mainnet.toml +``` + +Create test files that validate your deployments: + +```javascript +// e2e/tests/omnibus-mainnet.toml/basic-functionality.e2e.js +const { ethers } = require('ethers'); +const { expect } = require('chai'); + +describe('Basic Protocol Functionality', () => { + let provider, system; + + before(async () => { + provider = new ethers.providers.JsonRpcProvider('http://localhost:8545'); + // Load deployed contracts from Cannon state + const deployments = require('../../../deployments.json'); + system = deployments.system.CoreProxy; + }); + + it('should have correct owner configured', async () => { + const contract = new ethers.Contract(system.address, system.abi, provider); + const owner = await contract.owner(); + expect(owner).to.not.equal(ethers.constants.AddressZero); + }); +}); +``` + +[Screenshot placeholder: E2E test structure and example test file] + +### Best Practices + +#### Version Management + +1. **Package Versioning**: Use semantic versioning for your protocol packages +2. **Synchronized Updates**: Keep all omnibus files updated when core packages change +3. **Git Tagging**: Tag deployments for easy reference + +```bash +# After successful mainnet deployment +git tag -a v2.1.0-mainnet -m "Mainnet deployment v2.1.0" +git push origin v2.1.0-mainnet +``` + +### Advanced Patterns + +#### Multi-Chain Deployment + +For protocols deploying across multiple chains, you can selectively include or override additional components specific to different changes by adding them to `include`: + +```toml +# omnibus-base-mainnet.toml +include = [ + "tomls/settings.toml", + "tomls/core.toml", + "tomls/omnibus-base-mainnet/ccip-config.toml", # Cross-chain specific + "tomls/omnibus-base-mainnet/bridge-config.toml", +] +``` + +### Understanding the Clone Action + +An important aspect of deployments repositories is the use of the `clone` action to reference published packages. Unlike copying artifacts manually, `clone` reuses artifacts used on a local network release to replicate the same release on an actual live network. + +#### Publishing from Private Repositories + +Even if your main development repository is private, you can still publish packages to the Cannon registry for use in your deployments repository: + +1. **FRom your private repository**, tell Cannon to keep your code private: + ```toml + # at the top of your TOML file, under `name` and `version` + privateSourceCode = true # will prevent your solidity source codes from being packaged in public publish + ``` + +2. **From your private repository**, build and publish your packages: + ```bash + # In your private development repository + cannon build + cannon publish my-protocol-core:1.0.0 --chain-id 1 --private-key $DEPLOYER_KEY + ``` + +2. **In your deployments repository**, reference the published package: + ```toml + [clone.oracle_manager] + source = "my-protocol-core:1.0.0" + target = "my-protocol-core:1.0.0@main" + options.salt = "<%= settings.deployment_salt %>-oracle" + options.owner = "<%= settings.owner_address %>" + ``` + +#### Benefits of the Clone Pattern + +- **Immutable Packages**: Published packages are immutable and verifiable +- **Version Control**: Precise control over which package versions are deployed +- **Separation**: Complete separation between development and deployment workflows +- **Reproducibility**: Deployments are reproducible across different environments + +[Screenshot placeholder: CLI publishing from private repo and clone usage in deployments repo] + +### Integration with Development Workflow + +#### Artifact Synchronization + +Set up automation to keep deployment artifacts synchronized: + +```bash +#!/bin/bash +# scripts/sync-artifacts.sh +# Copy latest artifacts from main repository +rsync -av ../main-protocol/out/ ./artifacts/ +git add artifacts/ +git commit -m "Update artifacts to $(cd ../main-protocol && git rev-parse --short HEAD)" +``` + +#### CI/CD Integration + +Add GitHub Actions for automated verification of deployment plans prior to release: + +```yaml +# .github/workflows/test-deployments.yml +name: Test Deployments +on: + pull_request: + paths: ['omnibus-*.toml', 'tomls/**'] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '18' + - name: Install dependencies + run: yarn install + - name: Test Sepolia deployment + run: yarn build:sepolia + env: + INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }} +``` + +### Troubleshooting + +#### Common Issues + +**Problem**: "Package not found" errors during deployment +**Solution**: Ensure all referenced packages are published to the registry. You can also build the package locally to test it prior to publishing. + +**Problem**: Settings override not working +**Solution**: Check the order of includes - later files override earlier ones + +#### Debugging Workflow + +1. **Local Testing**: Always test with `--dry-run` first +2. **Network Validation**: Verify RPC connectivity and chain ID +3. **Package Resolution**: Check that all package references resolve correctly +4. **Log Analysis**: Review Cannon build logs for detailed error information diff --git a/packages/website/guides/queue-with-gitops.mdx b/packages/website/guides/queue-with-gitops.mdx new file mode 100644 index 000000000..993213837 --- /dev/null +++ b/packages/website/guides/queue-with-gitops.mdx @@ -0,0 +1,229 @@ +--- +title: Queue with GitOps +description: Learn how to use the Queue with GitOps functionality on the Cannon website to deploy protocols from Git repositories or IPFS. +before: + url: "deploy-onchain" + title: "Deploy Onchain" + description: "Deploy your protocol onchain." +after: + url: "publish" + title: "Publish Your Package" + description: "Publish your protocol to the Cannon explorer." +--- + +## Queue with GitOps + +The Queue with GitOps functionality allows you to deploy Cannon packages directly from Git repositories or IPFS hashes through the Cannon website interface. This is particularly useful for teams using Safe multisig wallets and wanting to make their deployments as declarative as possible. + + + Before you start + This guide assumes you have a Safe multisig wallet configured and are familiar with basic Cannon concepts. Make sure you have completed the [Setup](/learn/guides/setup) guide. + + +### Overview + +The Queue with GitOps feature enables you to: +- Deploy Cannon packages from GitHub repositories containing cannonfiles +- Resume partial deployments from IPFS hashes +- Preview transactions before execution (and the corresponding Git Diff of the changes) +- Execute deployments through Safe multisig wallets +- Publish the resulting package after deployment to the Cannon registry + +### Getting Started + +#### Step 1: Access the Queue Interface + +1. Navigate to the [Cannon website](https://usecannon.com) +2. Connect your wallet and ensure you're on the correct network +3. Go to the **Deploy** section and select **Queue with GitOps** + +[Screenshot placeholder: Navigation to Queue with GitOps interface] + +#### Step 2: Configure Your Safe + +Before queuing deployments, please ensure: + +1. Confirm you're on the correct network and Safe for your deployment +2. The Safe that you are executing the transaction on does not currently have staged transactions on https://app.safe.global + * Cannon uses its own staging service, so any transactions that are pending on the Safe app will conflict with transactions executed on the Cannon website. +2. Ensure you have a deployer EOA with sufficient funds to execute the upgrade transaction +3. The required signers are available + +[Screenshot placeholder: Safe configuration interface] + +### Deployment Methods + +The Queue with GitOps interface supports two primary deployment methods: + +#### Method 1: Deploy from Git Repository (reccomended for most tasks) + +Use this method when you have a Cannon project stored in a Git repository. + +##### Input Format +Provide a direct URL to your cannonfile in the repository. This should be the URL of the page you reach when you preview the file on GitHub. For example: +``` +https://github.com/usecannon/cannon/blob/dev/examples/sample-foundry-project/cannonfile.toml +``` + + + **NOTE:** The repository being deployed must be publicly accessible. If you do not want to expose your smart contract repositories, it is reccomended to [create a deployments repository](/learn/guides/deployments-repo) instead. + + Additionally, if the repository's branch checkout is too large, it can be difficult to download in your browser. + + + +You can also input a IPFS hash of a partial build completed with the Cannon CLI. This will be the IPFS hash of the partial build given by Cannon. For example: + +``` +ipfs://QmUGX7nJFBxiGfwunwTe1YnEHnStKibzuWusvzPmt4d5Yg +``` + + + + Before you can read the IPFS hash from the website, your partial build must be pinned to the IPFS network. You can do this with `cannon pin ipfs://QmUGX7nJFBxiGfwunwTe1YnEHnStKibzuWusvzPmt4d5Yg` + + + +##### Steps: +1. In the **Deployment Source** field, enter the URL to your cannonfile or partial IPFS hash +2. The system will automatically detect this as a Git deployment +3. Click the "Preview Transactions to Queue". The build will be completed client side in your browser. It may take a few minutes to generate. +4. Review the parsed cannonfile configuration, and use the buttons at the bottom of the page to stage it to the Safe. + +[Screenshot placeholder: Git repository input interface showing URL field and validation] + +#### After Staging +Your transaction will appear as pending on the deploy page of the Cannon website. You can click it to. + +It is reccomended to send the URL of the transaction to execute to other signers to simplify the signer process. Each signer can click "Sign" to add their signature. + + + Carefully validate all transaction data displayed by the website. + + + + When signing, verify that the data that is included in the transaction being signed by your wallet matches the data being displayed by the website. You can view tips on how to do this on [Safe's website](https://help.safe.global/en/articles/276344-how-to-verify-safe-wallet-transactions-on-a-hardware-wallet). + + +Once enough signatures have been accumulated, a wallet with gas tokens (aka ETH) can execute by using the `Execute` button on the page. + +### Configuration Options + +You can adjust the URLs of any servers or backends connected to by the website from the [Settings](/settings) page. For best results, it is reccomended to set your organization's URLs for: +* Any network provider RPCs that you have (ex. Optimism, Mainnet, your deployment network) +* Custom safe transaction services (if you are using a custom chain that isnt supported by main Safe transaction service) +* A IPFS endpoint, if your organization uses its own IPFS + +#### Previous Package Input + +When deploying upgrades or continuing deployments, you may need to specify a previous package: + +- **Package Reference**: Use the format `package-name:version@preset` (e.g., `my-protocol:1.0.0@main`) +- **IPFS URL**: Reference a specific IPFS deployment hash + +[Screenshot placeholder: Previous package input field with examples] + +#### Deployment Preview + +Before executing transactions, always preview your deployment: + +1. Click **Preview Transactions** after configuring your deployment source +2. Review the list of transactions that will be executed +3. Check gas estimates and transaction details +4. Verify contract addresses and function calls + +[Screenshot placeholder: Transaction preview interface showing list of pending transactions with gas estimates] + +### Executing Deployments + +#### Safe Transaction Flow + +Once you've previewed and confirmed your deployment: + +1. **Queue Transactions**: Click to add transactions to your Safe queue +2. **Review in Safe**: Switch to your Safe interface to review queued transactions +3. **Collect Signatures**: Have other Safe owners sign the transactions +4. **Execute**: Once threshold signatures are collected, execute the deployment + +[Screenshot placeholder: Safe transaction execution flow showing queued transactions and signature collection] + +#### Monitoring Deployment + +Track your deployment progress through several indicators: + +- **Build Status**: Shows compilation and transaction preparation progress +- **IPFS Status**: Indicates when artifacts are being uploaded to IPFS +- **Transaction Status**: Displays execution progress for each transaction + +[Screenshot placeholder: Deployment monitoring interface showing progress indicators] + +### Advanced Features + +#### Upgrading Existing Deployments + +When upgrading an existing protocol: + +1. Ensure your cannonfile includes proper version incrementing +2. Specify the previous package reference for state continuity +3. Review the upgrade diff to understand what changes will be applied +4. Test the upgrade on a testnet before mainnet deployment + +#### Handling Deployment Errors + +Common issues and solutions: + +- **Invalid Cannonfile URL**: Ensure the URL is publicly accessible and points to a valid cannonfile +- **IPFS Gateway Errors**: Try using a different IPFS gateway or wait and retry +- **Insufficient Funds**: Ensure your Safe has enough ETH for gas fees +- **Transaction Failures**: Review the transaction details and check for contract address conflicts + +[Screenshot placeholder: Error handling interface showing common error messages and suggested solutions] + +### Best Practices + +#### Security Considerations + +- **Verify Sources**: Always verify that Git repositories and IPFS hashes are from trusted sources +- **Review Transactions**: Carefully review all transactions before signing +- **Test First**: Deploy to testnets before mainnet +- **Monitor Deployments**: Keep track of deployment status and transaction confirmations + +#### Workflow Integration + +- **Version Control**: Tag your repository releases to ensure reproducible deployments +- **CI/CD Integration**: Consider integrating Cannon builds into your continuous deployment pipeline +- **Documentation**: Keep deployment logs and package references for future upgrades + +### Troubleshooting + +#### Common Issues + +**Problem**: "Invalid input" error when entering deployment source +**Solution**: Verify your URL format and ensure the cannonfile is publicly accessible + +**Problem**: Transactions fail during execution +**Solution**: Check that all deployer addresses have sufficient permissions and funds + +**Problem**: IPFS loading takes too long +**Solution**: Try using a different IPFS gateway in your settings + +[Screenshot placeholder: Troubleshooting interface showing error logs and diagnostic information] + +#### Getting Help + +If you encounter issues: +- Check the [Troubleshooting Guide](/learn/guides/troubleshooting) for common solutions +- Join the [Cannon Discord](https://discord.gg/cannon) for community support +- Review transaction details in your Safe interface +- Check network status and gas prices + +### Next Steps + +After successfully deploying with Queue with GitOps: + +1. **Verify Deployment**: Confirm all contracts are deployed correctly +2. **Update Documentation**: Record deployment addresses and transaction hashes +3. **Publish Package**: Consider [publishing your package](/learn/guides/publish) to make it discoverable +4. **Set Up Monitoring**: Implement monitoring for your deployed contracts + +The Queue with GitOps functionality streamlines the deployment process while maintaining the security benefits of multisig wallets, making it an essential tool for protocol teams operating in production environments. diff --git a/packages/website/src/constants/links.ts b/packages/website/src/constants/links.ts index 4e702ee5a..62da0d01a 100644 --- a/packages/website/src/constants/links.ts +++ b/packages/website/src/constants/links.ts @@ -15,6 +15,8 @@ export const links = { COMPARISON: '/learn/guides/comparison', BUILD_TROUBLESHOOTING: '/learn/guides/troubleshooting', MIGRATE: '/learn/guides/migrate', + QUEUE_WITH_GITOPS: '/learn/guides/get-started/queue-with-gitops', + DEPLOYMENTS_REPO: '/learn/guides/get-started/deployments-repo', CLI: '/learn/cli', CANNONFILE: '/learn/cannonfile', IPFS_DOWNLOAD: '/ipfs', diff --git a/packages/website/src/pages/learn/guides/guideLayout.tsx b/packages/website/src/pages/learn/guides/guideLayout.tsx index da7e18ab9..176341b52 100644 --- a/packages/website/src/pages/learn/guides/guideLayout.tsx +++ b/packages/website/src/pages/learn/guides/guideLayout.tsx @@ -36,6 +36,14 @@ const getStartedGuides = [ text: 'Deploy Onchain', href: `${links.GETSTARTED}/deploy-onchain`, }, + { + text: 'Queue with GitOps', + href: links.QUEUE_WITH_GITOPS, + }, + { + text: 'Create a Deployments Repository', + href: links.DEPLOYMENTS_REPO, + }, { text: 'Publish Your Package', href: `${links.GETSTARTED}/publish`,