Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 03e2bc1e11 | |||
| ccb3dc6f75 | |||
| ff32ec85c5 | |||
| 48c0351be3 | |||
| 5c7e4d45d4 | |||
| 8fe637e0e2 | |||
| f3d73c9160 | |||
| a6da45f6bf | |||
| 547d8ae314 | |||
| 1a874724c2 | |||
| 262a8be326 |
@@ -16,7 +16,7 @@ concurrency:
|
||||
jobs:
|
||||
check:
|
||||
name: Type-check & lint
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
name: Build & push worker image
|
||||
needs: check
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -55,12 +55,12 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to GHCR
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push worker image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
@@ -68,14 +68,14 @@ jobs:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/farhoodlabs/trebuchet:latest
|
||||
ghcr.io/farhoodlabs/trebuchet:sha-${{ github.sha }}
|
||||
git.farh.net/farhoodlabs/trebuchet:latest
|
||||
git.farh.net/farhoodlabs/trebuchet:sha-${{ github.sha }}
|
||||
|
||||
build-api:
|
||||
name: Build & push API image
|
||||
needs: check
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -87,12 +87,12 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to GHCR
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push API image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
@@ -102,5 +102,5 @@ jobs:
|
||||
push: true
|
||||
no-cache: true
|
||||
tags: |
|
||||
ghcr.io/farhoodlabs/trebuchet-api:latest
|
||||
ghcr.io/farhoodlabs/trebuchet-api:sha-${{ github.sha }}
|
||||
git.farh.net/farhoodlabs/trebuchet-api:latest
|
||||
git.farh.net/farhoodlabs/trebuchet-api:sha-${{ github.sha }}
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
jobs:
|
||||
preflight:
|
||||
name: Preflight
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
|
||||
@@ -35,7 +35,6 @@ jobs:
|
||||
if [[ -z "$LATEST" ]]; then
|
||||
echo "version=1.0.0-beta.1" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
# Extract N from 1.0.0-beta.N and increment
|
||||
N=$(echo "$LATEST" | grep -oE 'beta\.([0-9]+)' | grep -oE '[0-9]+')
|
||||
NEXT=$((N + 1))
|
||||
echo "version=1.0.0-beta.$NEXT" >> "$GITHUB_OUTPUT"
|
||||
@@ -47,9 +46,10 @@ jobs:
|
||||
build-docker:
|
||||
name: Build Docker (worker)
|
||||
needs: preflight
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -58,11 +58,12 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push worker image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
@@ -71,14 +72,15 @@ jobs:
|
||||
push: true
|
||||
provenance: mode=max
|
||||
sbom: true
|
||||
tags: farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}
|
||||
tags: git.farh.net/farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}
|
||||
|
||||
build-docker-api:
|
||||
name: Build Docker (API)
|
||||
needs: preflight
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -87,11 +89,12 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push API image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
@@ -101,15 +104,15 @@ jobs:
|
||||
push: true
|
||||
provenance: mode=max
|
||||
sbom: true
|
||||
tags: farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}
|
||||
tags: git.farh.net/farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}
|
||||
|
||||
sign-docker:
|
||||
name: Sign Docker images
|
||||
needs: [preflight, build-docker, build-docker-api]
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
outputs:
|
||||
worker_digest: ${{ steps.inspect-worker.outputs.digest }}
|
||||
api_digest: ${{ steps.inspect-api.outputs.digest }}
|
||||
@@ -118,57 +121,63 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Inspect worker image
|
||||
id: inspect-worker
|
||||
run: |
|
||||
docker buildx imagetools inspect "farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
docker buildx imagetools inspect "git.farh.net/farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "git.farh.net/farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Inspect API image
|
||||
id: inspect-api
|
||||
run: |
|
||||
docker buildx imagetools inspect "farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
docker buildx imagetools inspect "git.farh.net/farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "git.farh.net/farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
|
||||
|
||||
- name: Sign worker image
|
||||
run: cosign sign --yes "farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
env:
|
||||
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
run: cosign sign --yes --key env://COSIGN_PRIVATE_KEY "git.farh.net/farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
|
||||
- name: Sign API image
|
||||
run: cosign sign --yes "farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
env:
|
||||
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
run: cosign sign --yes --key env://COSIGN_PRIVATE_KEY "git.farh.net/farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
|
||||
- name: Verify worker image signature
|
||||
env:
|
||||
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }}
|
||||
run: |
|
||||
sleep 10
|
||||
cosign verify \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
--certificate-identity https://github.com/${{ github.repository }}/.github/workflows/release-beta.yml@${{ github.ref }} \
|
||||
"farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
cosign verify --key env://COSIGN_PUBLIC_KEY \
|
||||
"git.farh.net/farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
|
||||
- name: Verify API image signature
|
||||
env:
|
||||
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }}
|
||||
run: |
|
||||
cosign verify \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
--certificate-identity https://github.com/${{ github.repository }}/.github/workflows/release-beta.yml@${{ github.ref }} \
|
||||
"farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
cosign verify --key env://COSIGN_PUBLIC_KEY \
|
||||
"git.farh.net/farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
|
||||
publish-npm:
|
||||
name: Publish npm (beta)
|
||||
needs: [preflight, sign-docker]
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
jobs:
|
||||
preflight:
|
||||
name: Preflight
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
@@ -42,11 +42,12 @@ jobs:
|
||||
id: probe
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_URL: https://git.farh.net
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
npx semantic-release@25 --dry-run --no-ci 2>&1 | tee semantic-release.log
|
||||
npx -p semantic-release@25 -p semantic-release-gitea semantic-release --dry-run --no-ci 2>&1 | tee semantic-release.log
|
||||
|
||||
if grep -qi "the next release version is" semantic-release.log; then
|
||||
echo "should_release=true" >> "$GITHUB_OUTPUT"
|
||||
@@ -60,9 +61,10 @@ jobs:
|
||||
name: Build Docker (worker)
|
||||
needs: preflight
|
||||
if: needs.preflight.outputs.should_release == 'true'
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -71,11 +73,12 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push worker image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
@@ -85,16 +88,17 @@ jobs:
|
||||
provenance: mode=max
|
||||
sbom: true
|
||||
tags: |
|
||||
farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}
|
||||
farhoodlabs/trebuchet:latest
|
||||
git.farh.net/farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}
|
||||
git.farh.net/farhoodlabs/trebuchet:latest
|
||||
|
||||
build-docker-api:
|
||||
name: Build Docker (API)
|
||||
needs: preflight
|
||||
if: needs.preflight.outputs.should_release == 'true'
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -103,11 +107,12 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push API image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
@@ -118,16 +123,16 @@ jobs:
|
||||
provenance: mode=max
|
||||
sbom: true
|
||||
tags: |
|
||||
farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}
|
||||
farhoodlabs/trebuchet-api:latest
|
||||
git.farh.net/farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}
|
||||
git.farh.net/farhoodlabs/trebuchet-api:latest
|
||||
|
||||
sign-docker:
|
||||
name: Sign Docker images
|
||||
needs: [preflight, build-docker, build-docker-api]
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
outputs:
|
||||
worker_digest: ${{ steps.inspect-worker.outputs.digest }}
|
||||
api_digest: ${{ steps.inspect-api.outputs.digest }}
|
||||
@@ -136,57 +141,63 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Inspect worker image
|
||||
id: inspect-worker
|
||||
run: |
|
||||
docker buildx imagetools inspect "farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
docker buildx imagetools inspect "git.farh.net/farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "git.farh.net/farhoodlabs/trebuchet:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Inspect API image
|
||||
id: inspect-api
|
||||
run: |
|
||||
docker buildx imagetools inspect "farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
docker buildx imagetools inspect "git.farh.net/farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}"
|
||||
DIGEST="sha256:$(docker buildx imagetools inspect --raw "git.farh.net/farhoodlabs/trebuchet-api:${{ needs.preflight.outputs.version }}" | sha256sum | cut -d' ' -f1)"
|
||||
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
|
||||
|
||||
- name: Sign worker image
|
||||
run: cosign sign --yes "farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
env:
|
||||
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
run: cosign sign --yes --key env://COSIGN_PRIVATE_KEY "git.farh.net/farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
|
||||
- name: Sign API image
|
||||
run: cosign sign --yes "farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
env:
|
||||
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
run: cosign sign --yes --key env://COSIGN_PRIVATE_KEY "git.farh.net/farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
|
||||
- name: Verify worker image signature
|
||||
env:
|
||||
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }}
|
||||
run: |
|
||||
sleep 10
|
||||
cosign verify \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
--certificate-identity https://github.com/${{ github.repository }}/.github/workflows/release.yml@${{ github.ref }} \
|
||||
"farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
cosign verify --key env://COSIGN_PUBLIC_KEY \
|
||||
"git.farh.net/farhoodlabs/trebuchet@${{ steps.inspect-worker.outputs.digest }}"
|
||||
|
||||
- name: Verify API image signature
|
||||
env:
|
||||
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }}
|
||||
run: |
|
||||
cosign verify \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
--certificate-identity https://github.com/${{ github.repository }}/.github/workflows/release.yml@${{ github.ref }} \
|
||||
"farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
cosign verify --key env://COSIGN_PUBLIC_KEY \
|
||||
"git.farh.net/farhoodlabs/trebuchet-api@${{ steps.inspect-api.outputs.digest }}"
|
||||
|
||||
publish-npm:
|
||||
name: Publish npm
|
||||
needs: [preflight, sign-docker]
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -226,9 +237,9 @@ jobs:
|
||||
fi
|
||||
|
||||
release:
|
||||
name: Create GitHub release
|
||||
name: Create Gitea release
|
||||
needs: [preflight, publish-npm]
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
@@ -250,7 +261,8 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Create GitHub release
|
||||
- name: Create Gitea release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npx semantic-release@25
|
||||
GITEA_URL: https://git.farh.net
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: npx -p semantic-release@25 -p semantic-release-gitea semantic-release
|
||||
@@ -18,7 +18,7 @@ concurrency:
|
||||
jobs:
|
||||
rollback:
|
||||
name: Roll back npm beta dist-tag
|
||||
runs-on: runners-farhoodlabs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate target version
|
||||
id: target
|
||||
@@ -17,8 +17,8 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
rollback:
|
||||
name: Roll back npm, Docker, and GitHub release latest
|
||||
runs-on: runners-farhoodlabs
|
||||
name: Roll back npm and Docker latest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout tags
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
@@ -74,48 +74,44 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
- name: Log in to Gitea registry
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
registry: git.farh.net
|
||||
username: gitea-admin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Verify Docker image tag exists
|
||||
run: docker buildx imagetools inspect "farhoodlabs/trebuchet:${{ steps.target.outputs.version }}"
|
||||
run: docker buildx imagetools inspect "git.farh.net/farhoodlabs/trebuchet:${{ steps.target.outputs.version }}"
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
|
||||
|
||||
- name: Verify Docker image signature before rollback
|
||||
env:
|
||||
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }}
|
||||
run: |
|
||||
cosign verify \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
--certificate-identity "https://github.com/${{ github.repository }}/.github/workflows/release.yml@refs/heads/main" \
|
||||
"farhoodlabs/trebuchet:${{ steps.target.outputs.version }}"
|
||||
cosign verify --key env://COSIGN_PUBLIC_KEY \
|
||||
"git.farh.net/farhoodlabs/trebuchet:${{ steps.target.outputs.version }}"
|
||||
|
||||
- name: Move Docker latest
|
||||
run: |
|
||||
docker buildx imagetools create \
|
||||
--tag "farhoodlabs/trebuchet:latest" \
|
||||
"farhoodlabs/trebuchet:${{ steps.target.outputs.version }}"
|
||||
--tag "git.farh.net/farhoodlabs/trebuchet:latest" \
|
||||
"git.farh.net/farhoodlabs/trebuchet:${{ steps.target.outputs.version }}"
|
||||
|
||||
- name: Move npm latest
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npm dist-tag add "@trebuchet/cli@${{ steps.target.outputs.version }}" latest
|
||||
|
||||
- name: Mark GitHub release as latest
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: gh release edit "v${{ steps.target.outputs.version }}" --latest
|
||||
|
||||
- name: Show final npm dist-tags
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npm dist-tag ls @trebuchet/cli
|
||||
|
||||
- name: Verify Docker latest now points to target
|
||||
run: docker buildx imagetools inspect "farhoodlabs/trebuchet:latest"
|
||||
run: docker buildx imagetools inspect "git.farh.net/farhoodlabs/trebuchet:latest"
|
||||
|
||||
- name: Write summary
|
||||
run: |
|
||||
@@ -124,6 +120,9 @@ jobs:
|
||||
echo ""
|
||||
echo "- Target version: \`${{ steps.target.outputs.version }}\`"
|
||||
echo "- npm package: \`@trebuchet/cli\`"
|
||||
echo "- Docker image: \`farhoodlabs/trebuchet\`"
|
||||
echo "- GitHub release: \`v${{ steps.target.outputs.version }}\` marked as latest"
|
||||
echo "- Docker image: \`git.farh.net/farhoodlabs/trebuchet\`"
|
||||
echo ""
|
||||
echo "NOTE: Gitea determines the 'latest' release by date, not a flag."
|
||||
echo "To re-mark \`v${{ steps.target.outputs.version }}\` as the latest"
|
||||
echo "release on Gitea, edit the release in the UI to bump its date."
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
@@ -5,3 +5,5 @@ credentials/
|
||||
dist/
|
||||
repos/
|
||||
.turbo/
|
||||
cosign.key
|
||||
cosign.pub
|
||||
|
||||
+1
-8
@@ -9,13 +9,6 @@
|
||||
"npmPublish": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/github",
|
||||
{
|
||||
"successCommentCondition": false,
|
||||
"failCommentCondition": false,
|
||||
"releasedLabels": false
|
||||
}
|
||||
]
|
||||
"semantic-release-gitea"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ Comments must be **timeless** — no references to this conversation, refactorin
|
||||
|
||||
**Config:** `Dockerfile`, `apps/worker/configs/`, `apps/worker/prompts/`, `tsconfig.base.json` (shared compiler options), `turbo.json`, `biome.json`
|
||||
|
||||
**CI/CD:** `.github/workflows/ci.yml` (type-check, lint, build & push images to GHCR), `.github/workflows/release.yml` (Docker Hub push + GitHub release, manual dispatch)
|
||||
**CI/CD:** `.gitea/workflows/ci.yml` (type-check, lint, build & push images to GHCR), `.gitea/workflows/release.yml` (Docker Hub push + GitHub release, manual dispatch)
|
||||
|
||||
## Package Installation
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.14.0",
|
||||
"@kubernetes/client-node": "^1.4.0",
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"@trebuchet/worker": "workspace:*",
|
||||
"@temporalio/client": "^1.11.0",
|
||||
"hono": "^4.7.0",
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
export interface Config {
|
||||
readonly port: number;
|
||||
readonly mcpPort: number;
|
||||
readonly temporalAddress: string;
|
||||
readonly apiKey: string;
|
||||
readonly k8sNamespace: string;
|
||||
@@ -29,7 +28,6 @@ export function loadConfig(): Config {
|
||||
|
||||
return {
|
||||
port: Number(process.env.PORT) || 3000,
|
||||
mcpPort: Number(process.env.MCP_PORT) || 3100,
|
||||
temporalAddress: process.env.TEMPORAL_ADDRESS || 'hightower-temporal:7233',
|
||||
apiKey,
|
||||
k8sNamespace: process.env.K8S_NAMESPACE || 'hightower',
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
/**
|
||||
* MCP server for Hightower scan management.
|
||||
* Exposes scan-manager tools via the Model Context Protocol over HTTP.
|
||||
*/
|
||||
|
||||
import http from 'node:http';
|
||||
import type * as k8s from '@kubernetes/client-node';
|
||||
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||
import type { Client } from '@temporalio/client';
|
||||
import { z } from 'zod';
|
||||
import type { Config } from '../config.js';
|
||||
import { cancelScan, getReport, getScan, listScans, startScan } from '../services/scan-manager.js';
|
||||
import type { CreateScanInput } from '../types/api.js';
|
||||
|
||||
export interface McpServerDeps {
|
||||
readonly config: Config;
|
||||
readonly temporalClient: Client;
|
||||
readonly batchApi: k8s.BatchV1Api;
|
||||
readonly coreApi: k8s.CoreV1Api;
|
||||
}
|
||||
|
||||
function createMcpServer(deps: McpServerDeps): McpServer {
|
||||
const server = new McpServer(
|
||||
{ name: 'hightower', version: '1.0.0' },
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// === Tool: start_scan ===
|
||||
server.registerTool(
|
||||
'start_scan',
|
||||
{
|
||||
description: 'Start a new penetration test scan. Returns the scan ID and initial status.',
|
||||
inputSchema: z.object({
|
||||
targetUrl: z.string().describe('Target URL to scan (e.g., https://example.com)'),
|
||||
gitUrl: z.string().describe('Git URL of the repository to analyze (e.g., https://github.com/user/repo)'),
|
||||
workspace: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'Optional workspace name. Must match /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/. Defaults to auto-generated from target URL.',
|
||||
),
|
||||
gitRef: z.string().optional().describe('Optional Git branch/tag/commit to checkout before scanning.'),
|
||||
pipelineTesting: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe('If true, runs in minimal testing mode with fast retries (10s). Use for development.'),
|
||||
}),
|
||||
},
|
||||
async ({ targetUrl, gitUrl, workspace, gitRef, pipelineTesting }) => {
|
||||
const input: CreateScanInput = {
|
||||
targetUrl,
|
||||
gitUrl,
|
||||
workspace,
|
||||
...(gitRef !== undefined && { gitRef }),
|
||||
...(pipelineTesting !== undefined && { pipelineTesting }),
|
||||
};
|
||||
|
||||
const result = await startScan(deps.config, deps.batchApi, input);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: JSON.stringify(result, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// === Tool: get_scan ===
|
||||
server.registerTool(
|
||||
'get_scan',
|
||||
{
|
||||
description: 'Get the status, progress, and results of a running or completed scan.',
|
||||
inputSchema: z.object({
|
||||
scanId: z.string().describe('The scan ID returned from start_scan (e.g., hightower-worker-abc123)'),
|
||||
}),
|
||||
},
|
||||
async ({ scanId }) => {
|
||||
const result = await getScan(deps.config, deps.temporalClient, scanId);
|
||||
|
||||
if (!result) {
|
||||
return {
|
||||
content: [{ type: 'text' as const, text: `Scan '${scanId}' not found.` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: JSON.stringify(result, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// === Tool: list_scans ===
|
||||
server.registerTool(
|
||||
'list_scans',
|
||||
{
|
||||
description: 'List all running and historical scans.',
|
||||
inputSchema: z.object({}),
|
||||
},
|
||||
async () => {
|
||||
const results = await listScans(deps.config, deps.temporalClient, deps.batchApi);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: JSON.stringify(results, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// === Tool: cancel_scan ===
|
||||
server.registerTool(
|
||||
'cancel_scan',
|
||||
{
|
||||
description: 'Cancel a running scan by terminating its Kubernetes Job and Temporal workflow.',
|
||||
inputSchema: z.object({
|
||||
scanId: z.string().describe('The scan ID to cancel.'),
|
||||
}),
|
||||
},
|
||||
async ({ scanId }) => {
|
||||
await cancelScan(deps.config, deps.temporalClient, deps.batchApi, scanId);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Scan '${scanId}' cancellation requested.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// === Tool: get_report ===
|
||||
server.registerTool(
|
||||
'get_report',
|
||||
{
|
||||
description: 'Get the final security report for a completed scan.',
|
||||
inputSchema: z.object({
|
||||
scanId: z.string().describe('The scan ID to get the report for.'),
|
||||
}),
|
||||
},
|
||||
async ({ scanId }) => {
|
||||
const report = await getReport(deps.config, scanId);
|
||||
|
||||
if (!report) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Report for scan '${scanId}' not found.`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
content: [{ type: 'text' as const, text: report }],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
export async function startMcpServer(deps: McpServerDeps, port: number): Promise<http.Server> {
|
||||
const mcpServer = createMcpServer(deps);
|
||||
const transport = new StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: () => crypto.randomUUID(),
|
||||
});
|
||||
|
||||
// Cast to Transport — the SDK's Transport interface requires onclose: () => void
|
||||
// but StreamableHTTPServerTransport allows undefined (handled internally).
|
||||
await mcpServer.connect(transport as never);
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
transport.handleRequest(req, res, undefined);
|
||||
});
|
||||
|
||||
return new Promise<http.Server>((resolve, reject) => {
|
||||
server.on('error', reject);
|
||||
server.listen(port, () => {
|
||||
console.log(`MCP server listening on port ${port}`);
|
||||
resolve(server);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -4,3 +4,24 @@ description: API-driven AI pentester built on Shannon, deployed as a service on
|
||||
type: application
|
||||
version: 0.1.1
|
||||
appVersion: "1.0.0"
|
||||
home: https://git.farh.net/farhoodlabs/trebuchet
|
||||
sources:
|
||||
- https://git.farh.net/farhoodlabs/trebuchet
|
||||
maintainers:
|
||||
- name: farhoodlabs
|
||||
url: https://git.farh.net/farhoodlabs
|
||||
keywords:
|
||||
- security
|
||||
- pentesting
|
||||
- ai
|
||||
- kubernetes
|
||||
annotations:
|
||||
artifacthub.io/license: AGPL-3.0
|
||||
artifacthub.io/links: |
|
||||
- name: source
|
||||
url: https://git.farh.net/farhoodlabs/trebuchet
|
||||
artifacthub.io/images: |
|
||||
- name: worker
|
||||
image: git.farh.net/farhoodlabs/trebuchet:latest
|
||||
- name: api
|
||||
image: git.farh.net/farhoodlabs/trebuchet-api:latest
|
||||
|
||||
Generated
-566
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user