The project builds with:
makeThis runs the default debug target, which builds an optimized bundle using dev.env variables.
To start a hot-reloading build server with those same dev.env variables, run:
make watchBuild output is written to ./$(OUTDIR) if OUTDIR is a relative path, or just OUTDIR if the path is absolute. The default is ./dist.
- In Chrome navigate to the
chrome://extensionspage, and - enable "Developer mode" using the toggle in the upper right.
- Then, select "Load unpacked" in the upper left, and
- select the
distdirectory.
- In Firefox navigate to the
about:debuggingpage, and - select the "Load Temporrary Add-on..." button.
- Select the
dist/manifest.jsonfile and open it.
The Safari extension is integrated via the macOS (and iOS) app.
- Push your changes to a branch in this repo, and
- use
git-subtreeto pull in your branch as described in theUno-iOSREADME. - Open the
Uno.xcodeprojfile and run theUno (macOS)scheme. - Once the build launches, the extension will be available in Safari settings.
- If the extension does not show up, then you need to allow unsigned extensions.
- Under the
Advancedsettings tab, check "Show Develop menu in menu bar". - Then at the bottom of the
Developmenu, select: "Allow Unsigned Extensions". - Navigate to the
Extensionstab and enable the Uno browser extension.
{
// A listing of language IDs which should be validated by ESLint.
// NOTE: If not installed, ESLint will show an error.
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
// ESLint rules that should be executed when computing `codeActionsOnSave`.
// You can ignore rules using glob patterns (e.g.: "!@typescript-eslint/no-unsafe-assignment").
"eslint.codeActionsOnSave.rules": [
"*",
"!@typescript-eslint/*"
],
// Code actions to be executed upon save.
//
// NOTE: To improve performance, code actions
// should be "opt-in" on a per-extension basis.
"editor.codeActionsOnSave": {
"source.fixAll": false,
"source.organizeImports": false,
"source.fixAll.eslint": true,
},
}Dependencies are managed as Node modules. You can download and update dependencies without doing a full build using:
make depsFor unit-tests, we use Jest as our test-runner and assertion framework. To run unit tests, use:
make testFor integration tests, we use Playwright as our test-runner and assertion framework. To run integration tests, use:
make e2eTo view the last integration test report, run:
make e2e.reportTypeScript and ESLint are used to keep the code tidy.
TypeScript will automatically check for static type errors at build-time. However, you can manually perform type-checking with:
make typecheckLinting is integrated with the developer experience using a compatible IDE (e.g.: VSCode). However, linting can also be performed manually from your preferred shell with:
make lintESLint can even fix some errors automatically, including prettifying source code. Just run:
make formatRemove compiled sources (OUTDIR) using:
make cleanClobber node_modules as well using:
make clobberBy default, development builds target our internal production server at https://api.u1o.dev. Additionally:
- Analytics events go to a distinct development source in segment, but are not forwarded to amplitude or customer.io.
- Sentry errors are tagged as coming from the
developmentenvironment. - Native messaging uses the
local.uno.native_hostapplication specifier. - OAuth for Peekaboo happens using the
internalclient-id and credentials. - Feedback does not get published to the associated channel in Discord.
Generally, the above settings are appropriate for day-to-day development where you are making isolated changes to extension code. But sometimes you need to integrate a new feature including changes from the API server.
Here's how you can approach this scenario:
- Grab a preview URL for an API-related PR in the withuno/identity repo. You can find the URL by clicking on the DigitalOcean deployment link in a comment from our
gh-workflowbot. - Once the initial preview deployment has completed, grab the
ondigitalocean.applink near the top of the page. - Set the
API_SERVERenvironment variable to the value you just copied, then... - Build the extension!
For example:
make debug API_SERVER="https://identity-pr-102-lb4e4.ondigitalocean.app/"For convenience, there's a dedicated make command to build the extension targeting http://localhost:8080, which is where our local API server listens by default.
If you need to target a local instance of the API server, run:
make localUsing make will automatically install dependencies and run builds, but you can also manually call into NPM scripts for more granular control. First, install dependencies:
npm installThen, select your flavor of build server:
watchfor hot-reloading development, or...buildfor optimized bundling.
and pair with an environment variant:
dev.env— for local debugging/development usinghttps://api.u1o.devas the API server.e2e.env— for use in automated integration testing.local.env— for local debugging/development usinghttp://localhost:8080as the API server.internal.env— for distributing internal staging releases.prod.env— for distributing production releases.
The available commands are:
npm run watch.dev
npm run watch.e2e
npm run watch.local
npm run watch.internal
npm run watch.prod
npm run build.dev
npm run build.e2e
npm run build.local
npm run build.internal
npm run build.prodWe have two live environments: internal and production.
Both are full copies of our infrastructure and should be as identical as possible. The only difference is the domain name (and compute resources).
The internal infrastructure is hosted at https://api.u1o.dev, while production infrastruction is hosted at https://api.uno.app.
While developing, you create local, debug, or watch builds. When publishing a release, however, you create internal or release builds.
A good rule of thumb is: development builds are for yourself, while internal and production release builds are for others (either teammates internally, or general users, publicly).
However, don't hesitate to use an internal build if you need to test on live infrastructure (e.g. analytics, marketing, etc.).
Internal production releases can be made using:
make internalSend these to the team to try out new features for feedback and QA.
It's okay to use internal builds liberally. If you just added a new feature and need to build the analytics dashboard, make yourself an internal build to test on.
External production releases can be made using:
make releaseAn archive of build outputs will be created automatically with a name like uno-v1.x.x.zip, reflecting the version number injected into the extension manifest. This artifact can be uploaded directly to the appropriate browser extension web store.
To archive any build target automatically, you can set PACKAGE=true in your local environment. For example:
make debug PACKAGE=trueOur team is working to incrementally develop a robust Continuous Delivery pipeline for the web extension. The following release tasks are currently automated by CI/CD:
- Bump the patch version of the extension (e.g.:
v1.0.1 -> v1.0.2).- For merges into
next, a pre-release tag is appended to the version likev1.0.1 -> v1.0.2-next.0 -> v1.0.2-next.1 -> ....
- For merges into
- Builds the extension for an external release, then archives those deliverable outputs and the original source code.
- For merges into
next, aninternalrelease is created. - For merges into
main, aproductionrelease is created.
- For merges into
- Release notes are generated automatically, along with a tagged GitHub release.
When cutting a new release, download the artifacts from the relevant Internal or Production Release
In the future, we have plans to move the following manual tasks into CI/CD:
- Automatic publishing to the Chrome and Firefox extension storefronts.
- Automatic unit and integration testing against all PRs.
The vault schema is hosted on Github at withuno/vault_schema. To update the schema:
- change the tag version for
@withuno/vault-schemain package.json. - Then run:
npm update @withuno/vault-schemaand, npm install @withuno/vault-schema.- Confirm, in package-lock.json, that both
resolvedandversionhave changed, and thatfromindicates the correct tag version.