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.
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.
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.
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.
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.
-
Rebase the pull request branch onto
main
and push it. The pull request branch must be only one commit ahead ofmain
. -
Wait for CI to pass
-
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.
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.
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
.
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
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.
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}
.
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
- Account Manage ->
- APP-SPECIFIC PASSWORDS ->
- Generate password…
- a valid "Developer ID Application" certificate
- Certificates Add ->
- Developer ID Application
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
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.
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.
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.
-
Run
yarn upgrade-interactive
. -
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
orradicle-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
.
-
Update transitive dependencies: Remove
yarn.lock
and runyarn install
. -
Run
yarn dedupe
.
This section describes how to release a new version of Upstream.
gcloud
to upload artifacts. You need to ask for access to theradicle-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.
-
Create release candidate
-
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
-
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
-
-
Test the release
-
Wait for the Linux release candidate build on CI to pass.
-
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
-
Publish the CI artifacts as release candidate binaries.
./scripts/release.ts publish-rc-binaries
-
Create QA issues for the release that link to the release candidate binaries.
./scripts/release.ts create-qa-issues
-
Test the release by walking through the QA issues.
-
(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.)
-
Close the QA issues.
-
-
Publish and announce the release
-
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
-
Publish the release candidate binaries on
https://releases.radicle.xyz
, then create and publish a release tag../scripts/release.ts publish
-
Merge the pull request on
radicle.xyz
. -
Announce the release on discord and
radicle.community
. The community post should highlight the important changes in the release../scripts/release.ts announcements
-
Announce the release to the in-app update notification
./scripts/release.ts set-latest-release
-
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)
-
-
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.