Skip to content
This repository has been archived by the owner on Aug 1, 2022. It is now read-only.

Latest commit

 

History

History
413 lines (304 loc) · 13.5 KB

development.md

File metadata and controls

413 lines (304 loc) · 13.5 KB

Developer Guide

Development prerequisites

Running Upstream in development

To start Upstream for development run yarn start. For more advanced use cases see the section below on running multiple Upstream instances simultaneously.

Running Upstream with yarn start will use <repo_root>/sandbox/lnk_home as the default LNK_HOME value to isolate your development state. To reset the application state close Upstream, remove <repo_root>/sandbox/lnk_home and start Upstream again.

If you want to run Upstream against your real user data you need to build the application package with yarn dist. You can find the packaged application in the dist folder and run it from there.

Using the Git remote

Upstream provides the git-remote-rad binary to fetch and push Git repositories. If you want to use the rad remote in development you need to set the environment in your terminal:

source ./scripts/env

Make sure to source the script from the repository root.

Creating a Radicle identity in development mode

To create a Radicle identity during development, ensure you have the Radicle CLI installed. Then, before running rad auth, configure your shell environment for development by running:

source ./scripts/env

Now, you can run rad auth and follow the instructions, after which upstream will recognize your identity and proceed to the profile route.

Running multiple Upstream instances

We provide the scripts/devnet.ts tool for orchestrating multiple Radicle peers. This allows you to run Upstream instances or CLI commands for different peers and have the peers interact. Run yarn run devnet --help for a list of all commands.

The peers share data through a local Radicle Git server. To start the server run ./scripts/git-server-test.sh. The test server uses ephemeral storage: if you stop the server all data will be deleted.

The devnet tool uses numbers from 1 to 100 to identify and reference peers. For example, the following command will start Upstream for peer 1.

yarn run devnet upstream 1

The peer will be initialized and given the user name 1. The LNK_HOME for the peer is ./sandbox/devnet/1. The default passphrase for all devnet Upstream instances is asdf.

To use CLI commands like rad and upstream for a peer in your shell run

eval $(yarn run devnet shell 1)

Make sure you rebuild the UI before running instances:

yarn run webpack --config-name ui

The Upstream Proxy is rebuilt automatically.

Merging changes into the main branch

Maintainers are responsible for adding contribution to the main branch on the command line. We avoid the Github UI for merging changes. See the Licensing and DCO RFC for background on this.

After successful review, Github pull requests can be merged to main in two ways with a fast-forward merge being preferred.

Fast-forward merge (preferred)

  1. Rebase the pull request branch onto main and push it. The pull request branch must be only one commit ahead of main.

  2. Wait for CI to pass

  3. Check out main and merge the feature branch with

    git checkout main
    git merge --ff origin/feature-branch
    git push

If main has been updated since the rebase you need to repeat the steps.

Squash merge

You can squash merge a branch with

git checkout main
git merge --squash --signoff <branch-name>
git push

Please edit the commit message so that it adequately summarizes the change and retains all sign-offs by contributors.

UI

The UI is written in JavaScript, Svelte is our component language of choice and Electron wraps it all together into a native desktop experience. The UI code is split into /native and /ui.

For dependency management and script execution we use yarn. Code formatting is dictated by prettier and linting is provided by eslint. Both linting and formatting are enforced locally on a pre-commit basis with husky and lint-staged.

Additionally we run the same checks as separate build steps on our CI, just to make sure only properly formatted and lint-free code lands into main.

Running tests

We're using Playwright for end-to-end tests, for unit tests and tests that don't require a browser for rendering, we use Jest.

  • run Jest tests with: yarn jest

  • run Playwright tests with: yarn playwright test

  • run Playwright tests in debug mode with: PWDEBUG=console yarn playwright test

Running on Windows (experimental)

There might be issues due to long file paths on windows. A workaround for this is to set LNK_HOME to a root folder, for example:

$env:LNK_HOME="C:\lnk_home".

To try out Upstream on Windows, you can use a free VM provided by Microsoft.

Building an Upstream package for your platform

You can build and package Upstream with: yarn dist. The generated package will be in: dist/ as radicle-upstream-X.Y.Z.{dmg|AppImage|exe}.

Apple notarization

We do Apple notarization manually on developer machines. To set it up for the first time you'll need:

  • a paid Apple developer account
  • an App-specific password generated from your Apple ID, this allows the notarization script to run on behalf of our developer account
  • a valid "Developer ID Application" certificate

Once you've created the Developer ID Application certificate, download it locally and add it to your keychain by double clicking on the file.

Before building a notarized DMG, make sure you're connected to the internet, then run:

git checkout release-candidate/v0.X.XX
CSC_NAME="<YOUR_FIRST_NAME> <YOUR_LAST_NAME> (XXXXXXXXXX)" \
APPLE_ID="<YOUR_APPLE_ID_EMAIL>" \
APPLE_ID_PASSWORD="<APP_SPECIFIC_PASSWORD>" \
NOTARIZE=true \
yarn dist

upstream-proxy

All of Upstream's business logic tying together the Radicle code collaboration is provided to the UI via an HTTP API by a rust binary called upstream-proxy. It uses warp to serve a RESTish JSON API.

For dependency management and execution of common tasks we use Cargo. To get up to speed with common functionality and manifest file intricacies consult the exhaustive Cargo Book.

The proxy binary's lifecycle is managed by the main renderer of the UI in: native/main.ts. When running yarn dist it is bundled together into an application package by electron-builder.

Testing

The proxy and UI share the same test fixtures, if you haven't done it already, set up the test fixtures like so:

Then run tests as usual: cargo test --all-features --all-targets.

We strive for two kinds of tests: classic unit tests contained in implementation files and integration tests. The integration tests are meant to assert correctness of the API provided by the proxy, these can be found under proxy/tests. To find out where to place and how to lay out tests, check the Rust book test chapter.

CI setup

We run CI builds on Github Actions.

If the UI end-to-end tests fail, screenshots and logs for the failing tests are uploaded.

On pushes of the master branch we also build and upload distribution artifacts.

Updating NPM dependencies

  1. Run yarn upgrade-interactive.

  2. Select newer versions if appropriate

    • For major version upgrades review the changelog to assess the impact of breaking changes. The assessment should be included in the commit message.
    • The following packages cannot be upgraded to the next major version because we don’t support ES modules yet. See #2227. If possible, do a minor version upgrade.
      • node-fetch and @types/node-fetch
      • exit-hook
      • strip-ansi
      • execa
      • get-port
    • Don’t update radicle-contracts or radicle-avatar.
    • Don’t do a major upgrade of @types/node.
    • electron-builder shows ^22.14.5 as the latest version. This is not the latest version. Choose the version from the “Range” column. Same for @types/prompts, electron-builder
    • Don’t update graphql to v16. v15 is required as a peer dependency for @apollo/client.
  3. Update transitive dependencies: Remove yarn.lock and run yarn install.

  4. Run yarn dedupe.

Releases

This section describes how to release a new version of Upstream.

Prerequisites

  • gcloud to upload artifacts. You need to ask for access to the radicle-upstream-releases storage bucket.
  • hub version >= 2.14 to interact with GitHub’s API. See its documentation on how to configure access.
  • brew to update the Uptream cask.

All Github access tokens must have the public_repo scope.

Process

  1. Create release candidate

    1. Create a release candidate branch, bump the version, pre-fill the CHANGELOG.md file with a release note placeholder and create a pull-request.

      ./scripts/release.ts create-rc patch
    2. Open a draft pull request on radicle.xyz to update latest version.

      cd radicle.xyz
      git fetch --all
      git checkout -b update-latest-release origin/master
      echo -n X.Y.Z > partials/upstream-version.mustache && make
      git commit --all --message "Point to latest upstream release"
      hub pull-request --push --draft --no-edit
  2. Test the release

    1. Wait for the Linux release candidate build on CI to pass.

    2. Build and notarize the macOS x86_64 and arm64 binaries on your local machine.

      CSC_NAME=… \
      APPLE_ID=… \
      APPLE_ID_PASSWORD=… \
      NOTARIZE=true \
      yarn dist
    3. Publish the CI artifacts as release candidate binaries.

      ./scripts/release.ts publish-rc-binaries
    4. Create QA issues for the release that link to the release candidate binaries.

      ./scripts/release.ts create-qa-issues
    5. Test the release by walking through the QA issues.

    6. (Optional) To fix bugs, create a PR with the fixes based on the release candidate branch. Once it has been approved, squash merge it into the release candidate branch (see "Merging Pull Requests"). Then restart the "Test the release" step. (Skip creating a QA issue in 2.3.)

    7. Close the QA issues.

  3. Publish and announce the release

    1. Replace the release note placeholder in the CHANGELOG.md file with the actual release notes, amend the release commit and force-push the changes.

      vim CHANGELOG.md
      git commit --amend
      git push --force origin release-candidate/vX.Y.Z
    2. Publish the release candidate binaries on https://releases.radicle.xyz, then create and publish a release tag.

      ./scripts/release.ts publish
    3. Merge the pull request on radicle.xyz.

    4. Announce the release on discord and radicle.community. The community post should highlight the important changes in the release.

      ./scripts/release.ts announcements
    5. Announce the release to the in-app update notification

      ./scripts/release.ts set-latest-release
    6. Update the Homebrew cask

      brew tap homebrew/cask
      brew bump-cask-pr --version X.Y.Z radicle-upstream

      Note: disable commit signing before running these commands on macOS (see Homebrew/brew#3544)

  4. Finish the release by merging the release candidate branch into main.

    git checkout main
    git pull --ff-only
    git merge release-candidate/vX.Y.Z --signoff
    git push origin main
    rad push

    Merging may produce a merge commit on main instead of fast-forwarding. This is ok for release candidate branches.