diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2da1b74..9b98781 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,7 +5,6 @@ env: on: workflow_dispatch: - pull_request: push: branches: - "main" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9282e82..340b11f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,10 @@ name: test -on: workflow_dispatch +on: + workflow_dispatch: + push: + branches: + - "main" env: FOUNDRY_PROFILE: ci diff --git a/.husky/.pre-commit.sh b/.husky/.pre-commit.sh new file mode 100755 index 0000000..7f8b341 --- /dev/null +++ b/.husky/.pre-commit.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Temporary file to hold list of staged .sol files +STAGED_SOL_FILES=$(mktemp) +# Temporary file to hold list of all staged files for prettier +STAGED_FILES=$(mktemp) + +# List staged .sol files ignoring deleted files +git diff --cached --name-status -- '*.sol' | grep -v '^D' | cut -f2- > "$STAGED_SOL_FILES" +# List all staged files ignoring deleted files +git diff --cached --name-status | grep -v '^D' | cut -f2- > "$STAGED_FILES" + +# Run Solhint on staged .sol files, if any +if [ -s "$STAGED_SOL_FILES" ]; then + # If there are staged .sol files, run Solhint on them + SOLHINT_OUTPUT=$(cat "$STAGED_SOL_FILES" | xargs npx solhint --config ./.solhintrc) + SOLHINT_EXIT_CODE=$? + + if [ $SOLHINT_EXIT_CODE -ne 0 ]; then + echo "Solhint errors detected:" + echo "$SOLHINT_OUTPUT" + rm "$STAGED_SOL_FILES" "$STAGED_FILES" + exit $SOLHINT_EXIT_CODE + else + # Re-add the .sol files to include any automatic fixes by Solhint + cat "$STAGED_SOL_FILES" | xargs git add + fi +fi + +# Run Prettier and check for errors on staged files +if [ -s "$STAGED_FILES" ]; then + # Note: Using `--write` with Prettier to automatically fix formatting + PRETTIER_OUTPUT=$(cat "$STAGED_FILES" | xargs npx prettier --ignore-path .prettierignore --write) + PRETTIER_EXIT_CODE=$? + + if [ $PRETTIER_EXIT_CODE -ne 0 ]; then + echo "Prettier formatting errors detected:" + echo "$PRETTIER_OUTPUT" + rm "$STAGED_SOL_FILES" "$STAGED_FILES" + exit $PRETTIER_EXIT_CODE + else + # Re-add the files to include any formatting changes by Prettier + cat "$STAGED_FILES" | xargs git add + fi +fi + +# Clean up +rm "$STAGED_SOL_FILES" "$STAGED_FILES" + +# If we reach this point, either there were no issues or only warnings. +# Warnings are allowed, so we exit successfully. +exit 0 diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..c103ef1 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +./.husky/.pre-commit.sh diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..07c0b49 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,26 @@ +# directories +broadcast +cache +coverage +lib +node_modules +out +.husky + +# files +*.env +*.log +.DS_Store +lcov.info +package-lock.json +*.txt +*.toml +LICENSE +.solhintrc +.solhintignore +.prettierrc +.prettierignore +*.svg +.gitmodules +.gitignore +*.sh \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..94f9442 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,21 @@ +{ + "plugins": ["prettier-plugin-solidity"], + "overrides": [ + { + "files": "*.sol", + "options": { + "parser": "solidity-parse", + "printWidth": 80, + "tabWidth": 4, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": false + } + } + ], + "tabWidth": 4, + "printWidth": 80, + "trailingComma": "all", + "singleQuote": false, + "semi": true +} diff --git a/.solhintignore b/.solhintignore new file mode 100644 index 0000000..3be8890 --- /dev/null +++ b/.solhintignore @@ -0,0 +1,2 @@ +lib/ +out/ diff --git a/.solhintrc b/.solhintrc new file mode 100644 index 0000000..b2c64bb --- /dev/null +++ b/.solhintrc @@ -0,0 +1,13 @@ +{"extends": "solhint:recommended", + "rules": { + "compiler-version": ["error", ">=0.8.0"], + "func-visibility": ["error", { "ignoreConstructors": true }], + "named-parameters-mapping": "warn", + "no-console": "off", + "one-contract-per-file": "off", + "no-inline-assembly": "off", + "no-empty-blocks": "off", + "var-name-mixedcase": "off", + "no-global-import": "off" + } +} diff --git a/lint.yml b/lint.yml new file mode 100644 index 0000000..2da1b74 --- /dev/null +++ b/lint.yml @@ -0,0 +1,44 @@ +name: "Lint" + +env: + FOUNDRY_PROFILE: "ci" + +on: + workflow_dispatch: + pull_request: + push: + branches: + - "main" + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: "Check out the repo" + uses: actions/checkout@v3 + with: + submodules: recursive + - name: "Install Node.js" + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: "Install the Node.js dependencies" + run: npm install + + - name: Run linter and check for errors + id: lint + run: | + LINT_OUTCOME=$(npm run lint 2>&1 || true) # Prevent the step from failing immediately + echo "$LINT_OUTCOME" + echo "LINT_OUTCOME<> $GITHUB_ENV + echo "$LINT_OUTCOME" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + if echo "$LINT_OUTCOME" | grep -q " error "; then + echo "## Lint result" >> $GITHUB_STEP_SUMMARY + echo "❌ Failed due to errors" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "## Lint result" >> $GITHUB_STEP_SUMMARY + echo "✅ Passed or warnings found" >> $GITHUB_STEP_SUMMARY + fi diff --git a/package.json b/package.json new file mode 100644 index 0000000..0bd623b --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "shutter-staking", + "description": "Shutter Staking and Delegating Smart Contracts", + "version": "1.0.0", + "devDependencies": { + "husky": "9.0.10", + "prettier": "3.0.0", + "prettier-plugin-solidity": "1.2.0", + "solhint": "4.5.2" + }, + "scripts": { + "prepare": "husky", + "clean": "rm -rf cache out", + "build": "forge build", + "lint": "solhint --config ./.solhintrc --ignore-path .solhintignore '**/*.sol'", + "lint:write": "solhint --config ./.solhintrc --fix '**/*.sol'", + "prettier": "prettier --ignore-path .prettierignore --list-different './**/*'", + "prettier:write": "prettier --ignore-path .prettierignore --write './**/*'", + "test": "forge test", + "test:coverage": "forge coverage", + "test:coverage:report": "forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage" + } +}