add CLI support: clippy and fmt + rename commands #952
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CI | |
on: | |
push: | |
branches: | |
- main | |
- beta | |
- develop | |
paths-ignore: | |
- "**/CHANGELOG.md" | |
pull_request: | |
workflow_dispatch: | |
concurrency: | |
group: ${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }} | |
cancel-in-progress: true | |
jobs: | |
api-lint: | |
strategy: | |
fail-fast: false | |
matrix: | |
suite: [ordinals, runes] | |
runs-on: ubuntu-latest | |
defaults: | |
run: | |
working-directory: ./api/${{ matrix.suite }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Use Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: 'api/${{ matrix.suite }}/.nvmrc' | |
- name: Cache node modules | |
uses: actions/cache@v4 | |
env: | |
cache-name: cache-node-modules | |
with: | |
path: | | |
~/.npm | |
**/node_modules | |
key: ${{ runner.os }}-build-${{ matrix.suite }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-build-${{ matrix.suite }}-${{ env.cache-name }}- | |
${{ runner.os }}-build-${{ env.cache-name }}- | |
${{ runner.os }}-build- | |
${{ runner.os }}- | |
- name: Install deps | |
run: npm ci --audit=false | |
- name: Lint ESLint | |
run: npm run lint:eslint | |
- name: Lint Prettier | |
run: npm run lint:prettier | |
- name: Lint Unused Exports | |
run: npm run lint:unused-exports | |
api-test: | |
strategy: | |
fail-fast: false | |
matrix: | |
suite: [ordinals, runes] | |
defaults: | |
run: | |
working-directory: ./api/${{ matrix.suite }} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Use Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: 'api/${{ matrix.suite }}/.nvmrc' | |
- name: Cache node modules | |
uses: actions/cache@v4 | |
env: | |
cache-name: cache-node-modules | |
with: | |
path: | | |
~/.npm | |
**/node_modules | |
key: ${{ runner.os }}-build-${{ matrix.suite }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-build-${{ matrix.suite }}-${{ env.cache-name }}- | |
${{ runner.os }}-build-${{ env.cache-name }}- | |
${{ runner.os }}-build- | |
${{ runner.os }}- | |
- name: Install deps | |
run: npm ci --audit=false | |
- name: Setup integration environment | |
run: | | |
sudo ufw disable | |
npm run testenv:run -- -d | |
npm run testenv:logs -- --no-color &> docker-compose-logs.txt & | |
- name: Run tests | |
run: npm run test -- --coverage | |
- name: Upload coverage to Codecov | |
uses: codecov/codecov-action@v4 | |
with: | |
token: ${{ secrets.CODECOV_TOKEN }} | |
- name: Print integration environment logs | |
run: cat docker-compose-logs.txt | |
if: failure() | |
- name: Teardown integration environment | |
run: npm run testenv:stop | |
if: always() | |
rustfmt: | |
name: rust-fmt | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
suite: | |
- cli | |
- chainhook-sdk | |
- chainhook-postgres | |
- ordhook-core | |
- runes | |
defaults: | |
run: | |
working-directory: ./components/${{ matrix.suite }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Rustfmt Job Summary | |
run: | | |
# Run cargo and store the original output | |
CARGO_STATUS=0 | |
CARGO_OUTPUT=$(cargo fmt --all --manifest-path=Cargo.toml -- --config group_imports=StdExternalCrate,imports_granularity=Crate --color=always --check 2>/dev/null) || CARGO_STATUS=$? | |
if [ ${CARGO_STATUS} -eq 0 ]; then | |
cat <<MARKDOWN_INTRO >> $GITHUB_STEP_SUMMARY | |
# Rustfmt Results | |
The code is formatted perfectly! | |
MARKDOWN_INTRO | |
else | |
cat <<MARKDOWN_INTRO >> $GITHUB_STEP_SUMMARY | |
# Rustfmt Results | |
\`cargo fmt\` reported formatting errors in the following locations. | |
You can fix them by executing the following command and committing the changes. | |
\`\`\`bash | |
cargo bitcoin-indexer-fmt | |
\`\`\` | |
MARKDOWN_INTRO | |
echo "${CARGO_OUTPUT}" | | |
# Strip color codes | |
sed 's/\x1B\[[0-9;]*[A-Za-z]\x0f\?//g' | | |
# Strip (some) cursor movements | |
sed 's/\x1B.[A-G]//g' | | |
tr "\n" "\r" | | |
# Wrap each location into a HTML details | |
sed -E 's#Diff in ([^\r]*?)( at line |:)([[:digit:]]+):\r((:?[ +-][^\r]*\r)+)#<details>\n<summary>\1:\3</summary>\n\n```diff\n\4```\n\n</details>\n\n#g' | | |
tr "\r" "\n" >> $GITHUB_STEP_SUMMARY | |
fi | |
# Print the original cargo message | |
echo "${CARGO_OUTPUT}" | |
# Exit with the same status as cargo | |
exit "${CARGO_STATUS}" | |
clippy: | |
name: rust-clippy | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Run clippy | |
id: clippy | |
run: | | |
# Disable immediate exit on error | |
set +e | |
# Run clippy and capture output | |
cargo bitcoin-indexer-clippy-cli 2>&1 | tee /tmp/clippy_output.log | |
CLIPPY_EXIT_CODE=${PIPESTATUS[0]} | |
# Print output if clippy failed | |
if [ $CLIPPY_EXIT_CODE -ne 0 ]; then | |
echo "## ❌ Clippy Check Failed | |
To see and fix these issues, run: | |
\`\`\`bash | |
cargo bitcoin-indexer-clippy | |
\`\`\` | |
### Clippy Errors | |
\`\`\` | |
$(cat /tmp/clippy_output.log | grep -E '(error\:)|(warning\:)') | |
\`\`\`" >> $GITHUB_STEP_SUMMARY | |
fi | |
# Enable immediate exit on error again | |
set -e | |
exit $CLIPPY_EXIT_CODE | |
test: | |
strategy: | |
fail-fast: false | |
matrix: | |
suite: | |
- cli | |
- chainhook-sdk | |
- chainhook-postgres | |
- ordhook-core | |
- runes | |
runs-on: ubuntu-latest | |
defaults: | |
run: | |
working-directory: ./components/${{ matrix.suite }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Cache cargo | |
uses: actions/cache@v3 | |
with: | |
path: | | |
~/.cargo/bin/ | |
~/.cargo/registry/index/ | |
~/.cargo/registry/cache/ | |
~/.cargo/git/db/ | |
target/ | |
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
- name: Setup integration environment | |
run: | | |
sudo ufw disable | |
docker compose -f ../../dockerfiles/docker-compose.dev.postgres.yml up -d | |
docker compose -f ../../dockerfiles/docker-compose.dev.postgres.yml logs -t -f --no-color &> docker-compose-logs.txt & | |
- name: Install Rust | |
uses: actions-rust-lang/setup-rust-toolchain@v1 | |
- name: Run doc tests | |
run: | | |
cargo test --doc | |
- name: Run tests | |
run: | | |
cargo install --force cargo-tarpaulin | |
cargo tarpaulin --skip-clean --out lcov -- --test-threads=1 | |
- name: Upload coverage reports to Codecov | |
uses: codecov/codecov-action@v4 | |
with: | |
token: ${{ secrets.CODECOV_TOKEN }} | |
- name: Print integration environment logs | |
run: cat docker-compose-logs.txt | |
if: failure() | |
- name: Teardown integration environment | |
run: docker compose -f ../../dockerfiles/docker-compose.dev.postgres.yml down -v -t 0 | |
if: always() | |
semantic-release: | |
runs-on: ubuntu-latest | |
needs: [api-lint, api-test, test, rustfmt] | |
outputs: | |
new_release_version: ${{ steps.semantic.outputs.new_release_version }} | |
new_release_published: ${{ steps.semantic.outputs.new_release_published }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Semantic Release | |
uses: cycjimmy/semantic-release-action@v4 | |
id: semantic | |
# Only run on non-PR events or only PRs that aren't from forks | |
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
SEMANTIC_RELEASE_PACKAGE: ${{ github.event.repository.name }} | |
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_CRATES_IO_API_KEY }} | |
with: | |
semantic_version: 19 | |
extra_plugins: | | |
@semantic-release/[email protected] | |
@semantic-release/[email protected] | |
@semantic-release/[email protected] | |
[email protected] | |
build-publish: | |
runs-on: ubuntu-latest | |
needs: semantic-release | |
outputs: | |
docker_image_digest: ${{ steps.docker_push.outputs.digest }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Checkout tag | |
if: needs.semantic-release.outputs.new_release_version != '' | |
uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
ref: v${{ needs.semantic-release.outputs.new_release_version }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Docker Meta | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: | | |
hirosystems/bitcoin-indexer | |
tags: | | |
type=ref,event=branch | |
type=ref,event=pr | |
type=semver,pattern={{version}},value=${{ needs.semantic-release.outputs.new_release_version }},enable=${{ needs.semantic-release.outputs.new_release_version != '' }} | |
type=semver,pattern={{major}}.{{minor}},value=${{ needs.semantic-release.outputs.new_release_version }},enable=${{ needs.semantic-release.outputs.new_release_version != '' }} | |
type=raw,value=latest,enable={{is_default_branch}} | |
- name: Log in to DockerHub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_PASSWORD }} | |
- name: Build/Push Image | |
uses: docker/build-push-action@v5 | |
id: docker_push | |
with: | |
context: . | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
file: ./dockerfiles/components/bitcoin-indexer.dockerfile | |
build-args: | | |
GIT_COMMIT=${{ env.GITHUB_SHA_SHORT }} | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
# Only push if (there's a new release on main branch, or if building a non-main branch) and (Only run on non-PR events or only PRs that aren't from forks) | |
push: ${{ (github.ref != 'refs/heads/main' || needs.semantic-release.outputs.new_release_version != '') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} | |
api-build-publish: | |
strategy: | |
fail-fast: false | |
matrix: | |
suite: [ordinals, runes] | |
runs-on: ubuntu-latest | |
needs: semantic-release | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
token: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }} | |
fetch-depth: 0 | |
persist-credentials: false | |
- name: Checkout tag | |
if: needs.semantic-release.outputs.new_release_version != '' | |
uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
ref: v${{ needs.semantic-release.outputs.new_release_version }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Docker Meta | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: | | |
hirosystems/bitcoin-indexer-${{ matrix.suite }}-api | |
tags: | | |
type=ref,event=branch | |
type=ref,event=pr | |
type=semver,pattern={{version}},value=${{ needs.semantic-release.outputs.new_release_version }},enable=${{ needs.semantic-release.outputs.new_release_version != '' }} | |
type=semver,pattern={{major}}.{{minor}},value=${{ needs.semantic-release.outputs.new_release_version }},enable=${{ needs.semantic-release.outputs.new_release_version != '' }} | |
- name: Login to DockerHub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_PASSWORD }} | |
- name: Build/Tag/Push Image | |
uses: docker/build-push-action@v5 | |
with: | |
context: . | |
file: ./dockerfiles/components/${{ matrix.suite }}-api.dockerfile | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
# Only push if (there's a new release on main branch, or if building a non-main branch) and (Only run on non-PR events or only PRs that aren't from forks) | |
push: ${{ (github.ref != 'refs/heads/master' || needs.semantic-release.outputs.new_release_version != '') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} | |
deploy-dev: | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
network: [mainnet] | |
subenv: [blue] | |
needs: build-publish | |
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
env: | |
DEPLOY_ENV: dev | |
environment: | |
name: Development-${{ matrix.network }}-${{ matrix.subenv }} | |
url: https://platform.dev.hiro.so/ | |
steps: | |
- name: Checkout actions repo | |
uses: actions/checkout@v4 | |
with: | |
ref: main | |
token: ${{ secrets.GH_TOKEN }} | |
repository: ${{ secrets.DEVOPS_ACTIONS_REPO }} | |
- name: Deploy Ordhook build to Dev ${{ matrix.network }} ${{ matrix.subenv }} | |
uses: ./actions/deploy | |
with: | |
docker_image: ${{ env.DOCKER_IMAGE }} | |
docker_image_tag_or_digest: ${{ needs.build-publish.outputs.docker_image_digest }} | |
file_pattern: manifests/bitcoin/${{ matrix.network }}/ordhook/${{ env.DEPLOY_ENV }}/*/kustomization.yaml | |
subenv: ${{ matrix.subenv }} | |
gh_token: ${{ secrets.GH_TOKEN }} | |
auto-approve-dev: | |
runs-on: ubuntu-latest | |
if: needs.build-publish.outputs.new_release_published == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | |
needs: build-publish | |
steps: | |
- name: Approve pending deployments | |
run: | | |
sleep 5 | |
ENV_ID=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/hirosystems/ordhook/actions/runs/${{ github.run_id }}/pending_deployments" | jq -r '.[0].environment.id // empty') | |
if [[ "${ENV_IDS}" != "[]" ]]; then | |
curl -s -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/hirosystems/ordhook/actions/runs/${{ github.run_id }}/pending_deployments" -d "{\"environment_ids\":[${ENV_ID}],\"state\":\"approved\",\"comment\":\"auto approve\"}" | |
fi | |
deploy-staging: | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
network: [mainnet] | |
subenv: [blue] | |
needs: | |
- build-publish | |
- deploy-dev | |
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
env: | |
DEPLOY_ENV: stg | |
environment: | |
name: Staging-${{ matrix.network }}-${{ matrix.subenv }} | |
url: https://platform.stg.hiro.so/ | |
steps: | |
- name: Checkout actions repo | |
uses: actions/checkout@v4 | |
with: | |
ref: main | |
token: ${{ secrets.GH_TOKEN }} | |
repository: ${{ secrets.DEVOPS_ACTIONS_REPO }} | |
- name: Deploy Ordhook build to Stg ${{ matrix.network }} ${{ matrix.subenv }} | |
uses: ./actions/deploy | |
with: | |
docker_image: ${{ env.DOCKER_IMAGE }} | |
docker_image_tag_or_digest: ${{ needs.build-publish.outputs.docker_image_digest }} | |
file_pattern: manifests/bitcoin/${{ matrix.network }}/ordhook/${{ env.DEPLOY_ENV }}/*/kustomization.yaml | |
subenv: ${{ matrix.subenv }} | |
gh_token: ${{ secrets.GH_TOKEN }} | |
auto-approve-stg: | |
runs-on: ubuntu-latest | |
if: needs.build-publish.outputs.new_release_published == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | |
needs: | |
- build-publish | |
- deploy-dev | |
steps: | |
- name: Approve pending deployments | |
run: | | |
sleep 5 | |
ENV_ID=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/hirosystems/ordhook/actions/runs/${{ github.run_id }}/pending_deployments" | jq -r '.[0].environment.id // empty') | |
if [[ "${ENV_IDS}" != "[]" ]]; then | |
curl -s -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/hirosystems/ordhook/actions/runs/${{ github.run_id }}/pending_deployments" -d "{\"environment_ids\":[${ENV_ID}],\"state\":\"approved\",\"comment\":\"auto approve\"}" | |
fi | |
deploy-prod: | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
network: [mainnet] | |
subenv: [blue, green] | |
needs: | |
- build-publish | |
- deploy-staging | |
if: needs.build-publish.outputs.new_release_published == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | |
env: | |
DEPLOY_ENV: prd | |
environment: | |
name: Production-${{ matrix.network }}-${{ matrix.subenv }} | |
url: https://platform.hiro.so/ | |
steps: | |
- name: Checkout actions repo | |
uses: actions/checkout@v4 | |
with: | |
ref: main | |
token: ${{ secrets.GH_TOKEN }} | |
repository: ${{ secrets.DEVOPS_ACTIONS_REPO }} | |
- name: Deploy Ordhook build to Prd ${{ matrix.network }} ${{ matrix.subenv }} | |
uses: ./actions/deploy | |
with: | |
docker_image: ${{ env.DOCKER_IMAGE }} | |
docker_image_tag_or_digest: ${{ needs.build-publish.outputs.docker_image_digest }} | |
file_pattern: manifests/bitcoin/${{ matrix.network }}/ordhook/${{ env.DEPLOY_ENV }}/*/kustomization.yaml | |
subenv: ${{ matrix.subenv }} | |
gh_token: ${{ secrets.GH_TOKEN }} |