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] 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-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ 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] 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-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ 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() test: strategy: fail-fast: false matrix: suite: - ordhook-cli - ordhook-core - chainhook-sdk - chainhook-postgres 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: Update Rust run: | rustup update cargo install --force cargo-tarpaulin - name: Run tests run: | 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] 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/changelog@6.0.3 @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 conventional-changelog-conventionalcommits@6.1.0 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/ordhook 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/ordhook.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] 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/${{ 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 }}