Skip to content
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
3 changes: 2 additions & 1 deletion .shared/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules/
.yarn/
dist/
*.log
.DS_Store
Expand All @@ -12,4 +13,4 @@ artifacts/
*.swp
*.swo
*~
.idea/
.idea/
1 change: 1 addition & 0 deletions .shared/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
23 changes: 18 additions & 5 deletions .shared/INTEGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ If `npm install file:./.shared` fails because of peer dependency conflicts (comm
Toolbox still requiring `@types/chai@^4`), rerun with `--legacy-peer-deps` to reuse the lockfile the
repo already trusts.

> Heads-up: `yarn install --mode=update-lockfile` updates the lockfile only—it skips linking. Run a
> plain `yarn install` afterwards when the repository uses `nodeLinker: node-modules`; otherwise new
> shared dependencies (`@safe-global/*`, etc.) will be missing during the first `make roles.*` run.

#### Hook up the shared Makefile

Add the following to the repository `Makefile` (create one if it does not exist):
Expand All @@ -71,6 +75,8 @@ ROLES_REVOKE_ARGS ?=

> Tip: When you rely on `?=` for these defaults, declare the block *before* `include .shared/Makefile`. The shared file seeds empty placeholders during the include, so setting them earlier (or switching to `:=` afterwards) keeps `make roles.scan` / `make roles.transfer` wired up with sensible defaults.

Have repo-specific `slither` automation or a custom `help` target? Top-level duplicates trigger GNU Make warnings. Set `SHARED_ENABLE_SLITHER_TARGETS := 0` (and drop bespoke `help:` rules) ahead of the include when you need to preserve local implementations.

With those in place you can invoke `make roles.scan`, `make roles.transfer`, or `make roles.revoke` directly. The deployer / governance addresses are pulled from the manifest, and `roles.revoke` also reads the Safe configuration (`safe.safeAddress` / `safe.chainId`) unless you override them explicitly. To customise behaviour on the fly, pass the exposed variables inline:

```bash
Expand Down Expand Up @@ -111,13 +117,19 @@ This keeps editor integrations, ad-hoc `yarn prettier` runs, and the guardrails

#### Install the shared git hooks

Enable the pre-commit and pre-push hooks so formatting and guardrails run locally before code reaches CI:
Enable the shared git hooks so formatting and guardrails run locally before code reaches CI:

```bash
node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks
node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks # installs the pre-push hook
node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks --include-pre-commit-hook # opt into the pre-commit hook
```

The pre-commit hook writes staged files with Prettier and runs ESLint; the pre-push hook executes the shared guardrail suite with `--fail-fast`. Because the hook scripts live inside `.shared`, future updates to the tooling automatically flow into every repository.
The pre-push hook executes the shared guardrail suite with `--fail-fast`, runs Prettier/ESLint/Solhint, and now
executes `npx hardhat test` by default. Set `SHARED_HARDHAT_PRE_PUSH_PRETTIER=0` or `SHARED_HARDHAT_PRE_PUSH_TEST=0`
to opt out temporarily, or override the test command with `SHARED_HARDHAT_PRE_PUSH_TEST_CMD="yarn test --runInBand"`.
Because the hook scripts live inside `.shared`, future updates to the tooling automatically flow into every
repository. Add `--include-pre-commit-hook` whenever you want the additional staged-file linting and compile guard that
the shared pre-commit hook provides.

> Prefer automation over manual flags? When you have access to this repository
> locally, `bash path/to/scripts/subtree/add.sh --help` prints the non-
Expand Down Expand Up @@ -339,8 +351,9 @@ npm run validate:matrix -- --config configs/validation.networks.json --report re

Once minimal integration is verified, consider:

- [ ] Set up git hooks: `node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks`
- Pre-commit executes guardrails and staged-file heuristics; enable Prettier with `SHARED_HARDHAT_PRE_COMMIT_PRETTIER=1` and contract compilation with `SHARED_HARDHAT_PRE_COMMIT_COMPILE=1` when you want them enforced locally.
- [ ] Set up git hooks: `node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks` (add `--include-pre-commit-hook`
to opt into the shared pre-commit checks)
- Pre-commit executes guardrails and staged-file heuristics; keep Prettier on unless you opt out (`SHARED_HARDHAT_PRE_COMMIT_PRETTIER=0`) and compile contracts by default (`SHARED_HARDHAT_PRE_COMMIT_COMPILE=0` to skip).
- Pre-push reruns guardrails, optionally runs tests (`SHARED_HARDHAT_PRE_PUSH_TEST=1`) or a custom command (`SHARED_HARDHAT_PRE_PUSH_TEST_CMD="yarn test --runInBand"`), enables Prettier with `SHARED_HARDHAT_PRE_PUSH_PRETTIER=1`, and requires Slither only on `main`/`master`/`develop`.
- [ ] Add shared CI workflow: `cp .shared/ci/shared-guardrails.yml .github/workflows/` (runs lint + sanity checks, Hardhat compile, and tests with a summary step)
- [ ] Configure the deploy ID sanity check (`sanity:deploy-ids` npm script or direct call with repo-specific `--deploy-ids/--deploy-root` arguments)
Expand Down
20 changes: 13 additions & 7 deletions .shared/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,21 +271,27 @@ Each command performs a guarded dry-run first, printing the planned changes and
### Setting Up Git Hooks

```bash
# Install just the shared hooks (skips configs/CI/package scripts)
# Install the default shared hook (pre-push only; skips configs/CI/package scripts)
node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks

# Opt into the optional pre-commit hook as well
node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks --include-pre-commit-hook

# Force overwrite existing hooks
node_modules/.bin/ts-node .shared/scripts/setup.ts --hooks --force
```

The shared pre-commit hook runs the guardrail suite (Prettier, ESLint, Solhint) and checks staged Solidity/tests for
`console.log` or lingering `.only`. Prettier is skipped by default—set `SHARED_HARDHAT_PRE_COMMIT_PRETTIER=1` to turn it
on. Contract compilation is opt-in as well (`SHARED_HARDHAT_PRE_COMMIT_COMPILE=1`).
`console.log` or lingering `.only`. Prettier runs by default—set `SHARED_HARDHAT_PRE_COMMIT_PRETTIER=0` to skip it
temporarily. Contract compilation is also enabled unless you opt out (`SHARED_HARDHAT_PRE_COMMIT_COMPILE=0`).

The pre-push hook reruns guardrails (Prettier enabled by default—set
`SHARED_HARDHAT_PRE_PUSH_PRETTIER=0` to skip), executes tests by default (opt out with
`SHARED_HARDHAT_PRE_PUSH_TEST=0`), and requires Slither only on long-lived branches (`main`, `master`, `develop`).
Customize the test command via `SHARED_HARDHAT_PRE_PUSH_TEST_CMD="yarn test --runInBand"`.

The pre-push hook reruns guardrails (Prettier disabled unless `SHARED_HARDHAT_PRE_PUSH_PRETTIER=1`), optionally
executes tests, and requires Slither only on long-lived branches (`main`, `master`, `develop`). Enable automated test
runs with `SHARED_HARDHAT_PRE_PUSH_TEST=1` or customize the command via
`SHARED_HARDHAT_PRE_PUSH_TEST_CMD="yarn test --runInBand"`.
By default only the pre-push hook is installed; re-run the setup command with `--include-pre-commit-hook` whenever you
want the additional pre-commit automation.

### Updating Shared Tools

Expand Down
162 changes: 81 additions & 81 deletions .shared/configs/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import path from "node:path";
import { fileURLToPath } from "node:url";
import path from 'node:path';
import { fileURLToPath } from 'node:url';

import { fixupPluginRules } from "@eslint/compat";
import { FlatCompat } from "@eslint/eslintrc";
import js from "@eslint/js";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
import eslintComments from "eslint-plugin-eslint-comments";
import _import from "eslint-plugin-import";
import jsdoc from "eslint-plugin-jsdoc";
import json from "eslint-plugin-json";
import prettier from "eslint-plugin-prettier";
import simpleImportSort from "eslint-plugin-simple-import-sort";
import unusedImports from "eslint-plugin-unused-imports";
import globals from "globals";
import { fixupPluginRules } from '@eslint/compat';
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import eslintComments from 'eslint-plugin-eslint-comments';
import _import from 'eslint-plugin-import';
import jsdoc from 'eslint-plugin-jsdoc';
import json from 'eslint-plugin-json';
import prettier from 'eslint-plugin-prettier';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
import unusedImports from 'eslint-plugin-unused-imports';
import globals from 'globals';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
Expand All @@ -25,61 +25,61 @@ const compat = new FlatCompat({
export default [
{
ignores: [
"**/artifacts/**",
"**/bot/**",
"**/cache/**",
"**/coverage/**",
"**/deployments/**",
"**/lib/**",
"**/node_modules/**",
"**/reports/**",
"**/typechain-types/**",
"**/.certora_internal/**",
"**/.shared/**",
"**/.yarn/**",
'**/artifacts/**',
'**/bot/**',
'**/cache/**',
'**/coverage/**',
'**/deployments/**',
'**/lib/**',
'**/node_modules/**',
'**/reports/**',
'**/typechain-types/**',
'**/.certora_internal/**',
'**/.shared/**',
'**/.yarn/**',
],
},
{
files: [
"*.cjs",
"*.cts",
"*.js",
"*.mjs",
"*.mts",
"*.ts",
"config/**/*.{ts,js}",
"deploy/**/*.{ts,js}",
"scripts/**/*.{ts,js}",
"test/**/*.{ts,js}",
"typescript/**/*.{ts,js}",
'*.cjs',
'*.cts',
'*.js',
'*.mjs',
'*.mts',
'*.ts',
'config/**/*.{ts,js}',
'deploy/**/*.{ts,js}',
'scripts/**/*.{ts,js}',
'test/**/*.{ts,js}',
'typescript/**/*.{ts,js}',
],
},
...compat.extends("plugin:eslint-comments/recommended", "plugin:jsdoc/recommended", "prettier"),
...compat.extends('plugin:eslint-comments/recommended', 'plugin:jsdoc/recommended', 'prettier'),
{
plugins: {
"@typescript-eslint": typescriptEslint,
"eslint-comments": eslintComments,
'@typescript-eslint': typescriptEslint,
'eslint-comments': eslintComments,
import: fixupPluginRules(_import),
jsdoc,
json,
prettier,
"simple-import-sort": simpleImportSort,
"unused-imports": unusedImports,
'simple-import-sort': simpleImportSort,
'unused-imports': unusedImports,
},
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: "module",
sourceType: 'module',
},
globals: {
...globals.node,
...globals.browser,
},
},
rules: {
"max-len": [
"error",
'max-len': [
'error',
{
code: 140,
ignoreUrls: true,
Expand All @@ -89,60 +89,60 @@ export default [
ignoreComments: true,
},
],
"padding-line-between-statements": [
"error",
'padding-line-between-statements': [
'error',
{
blankLine: "always",
prev: ["*"],
next: ["block-like"],
blankLine: 'always',
prev: ['*'],
next: ['block-like'],
},
],
"eslint-comments/require-description": "error",
"json/*": [
"error",
'eslint-comments/require-description': 'error',
'json/*': [
'error',
{
allowComments: true,
},
],
"prettier/prettier": [
"error",
'prettier/prettier': [
'error',
{
printWidth: 140,
tabWidth: 2,
useTabs: false,
singleQuote: false,
semi: true,
trailingComma: "all",
trailingComma: 'all',
bracketSpacing: true,
arrowParens: "always",
endOfLine: "auto",
arrowParens: 'always',
endOfLine: 'auto',
},
],
"simple-import-sort/exports": "error",
"simple-import-sort/imports": "error",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
'simple-import-sort/exports': 'error',
'simple-import-sort/imports': 'error',
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'warn',
{
vars: "all",
varsIgnorePattern: "^_",
args: "after-used",
argsIgnorePattern: "^_",
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_',
},
],
"import/first": "error",
"import/newline-after-import": "error",
"import/no-duplicates": "error",
"jsdoc/require-jsdoc": "error",
"jsdoc/require-description": "error",
"jsdoc/require-param-description": "warn",
"jsdoc/require-param-type": "off",
"jsdoc/require-returns": "off",
"jsdoc/require-returns-description": "off",
"jsdoc/require-returns-type": "off",
"jsdoc/tag-lines": [
"error",
"never",
'import/first': 'error',
'import/newline-after-import': 'error',
'import/no-duplicates': 'error',
'jsdoc/require-jsdoc': 'error',
'jsdoc/require-description': 'error',
'jsdoc/require-param-description': 'warn',
'jsdoc/require-param-type': 'off',
'jsdoc/require-returns': 'off',
'jsdoc/require-returns-description': 'off',
'jsdoc/require-returns-type': 'off',
'jsdoc/tag-lines': [
'error',
'never',
{
startLines: 1,
},
Expand Down
8 changes: 4 additions & 4 deletions .shared/configs/prettier.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ module.exports = {
useTabs: false,
singleQuote: false,
semi: true,
trailingComma: "all",
trailingComma: 'all',
bracketSpacing: true,
arrowParens: "always",
plugins: ["prettier-plugin-solidity"],
arrowParens: 'always',
plugins: ['prettier-plugin-solidity'],
overrides: [
{
files: "*.sol",
files: '*.sol',
options: {
tabWidth: 4,
printWidth: 120,
Expand Down
10 changes: 5 additions & 5 deletions .shared/hooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ run_guardrails() {
fi

GUARDRAIL_ARGS="--fail-fast"
if [ "${SHARED_HARDHAT_PRE_COMMIT_PRETTIER:-0}" = "0" ]; then
if [ "${SHARED_HARDHAT_PRE_COMMIT_PRETTIER:-1}" = "0" ]; then
GUARDRAIL_ARGS="$GUARDRAIL_ARGS --skip-prettier"
echo "${YELLOW}Skipping Prettier check (set SHARED_HARDHAT_PRE_COMMIT_PRETTIER=1 to enable).${NC}"
echo "${YELLOW}Skipping Prettier check (set SHARED_HARDHAT_PRE_COMMIT_PRETTIER=1 to re-enable).${NC}"
fi
if [ "${SHARED_HARDHAT_PRE_COMMIT_SOLHINT:-1}" = "0" ]; then
GUARDRAIL_ARGS="$GUARDRAIL_ARGS --skip-solhint"
Expand Down Expand Up @@ -70,8 +70,8 @@ run_guardrails() {
}

run_compile_if_opt_in() {
if [ "${SHARED_HARDHAT_PRE_COMMIT_COMPILE:-0}" = "0" ]; then
echo "${YELLOW}Skipping Hardhat compile (enable via SHARED_HARDHAT_PRE_COMMIT_COMPILE=1).${NC}"
if [ "${SHARED_HARDHAT_PRE_COMMIT_COMPILE:-1}" = "0" ]; then
echo "${YELLOW}Skipping Hardhat compile (set SHARED_HARDHAT_PRE_COMMIT_COMPILE=1 to re-enable).${NC}"
return 0
fi

Expand All @@ -85,7 +85,7 @@ run_compile_if_opt_in() {
return 0
fi

echo "${RED}Contract compilation failed. Fix issues or unset SHARED_HARDHAT_PRE_COMMIT_COMPILE to skip this step.${NC}"
echo "${RED}Contract compilation failed. Fix issues or set SHARED_HARDHAT_PRE_COMMIT_COMPILE=0 to skip this step.${NC}"
return 1
}

Expand Down
Loading