From e69b9289b4e6f704e9a641a284b16e1bc81536a1 Mon Sep 17 00:00:00 2001 From: Gregory Schofield Date: Wed, 9 Jul 2025 14:20:34 -0400 Subject: [PATCH 1/2] Convert omnibus to goreleaser and simplify releasing. Signed-off-by: Gregory Schofield --- .github/workflows/build-and-release.yaml | 297 ----------------------- .github/workflows/build.yml | 166 +++++++++++++ .github/workflows/check-version.yaml | 18 -- .github/workflows/release.yml | 48 ++++ .gitignore | 3 +- .goreleaser.yaml | 46 ++++ VERSION | 1 - docker/omnibus/ubuntu/Dockerfile | 19 -- omnibus/GEMFAST-EULA.md | 0 omnibus/Gemfile | 4 - omnibus/Gemfile.lock | 136 ----------- omnibus/config/projects/gemfast.rb | 20 -- omnibus/config/software/caddy.rb | 21 -- omnibus/config/software/gemfast.rb | 31 --- omnibus/files/caddy/caddy.service | 39 --- omnibus/files/gemfast/auth_model.conf | 12 - omnibus/files/gemfast/gemfast.hcl | 67 ----- omnibus/files/gemfast/gemfast.service | 16 -- omnibus/files/gemfast/gemfast_acl.csv | 10 - omnibus/package-scripts/gemfast/postinst | 37 --- omnibus/package-scripts/gemfast/preinst | 16 -- 21 files changed, 262 insertions(+), 745 deletions(-) delete mode 100644 .github/workflows/build-and-release.yaml create mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/check-version.yaml create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser.yaml delete mode 100644 VERSION delete mode 100644 docker/omnibus/ubuntu/Dockerfile delete mode 100644 omnibus/GEMFAST-EULA.md delete mode 100644 omnibus/Gemfile delete mode 100644 omnibus/Gemfile.lock delete mode 100644 omnibus/config/projects/gemfast.rb delete mode 100644 omnibus/config/software/caddy.rb delete mode 100644 omnibus/config/software/gemfast.rb delete mode 100644 omnibus/files/caddy/caddy.service delete mode 100644 omnibus/files/gemfast/auth_model.conf delete mode 100644 omnibus/files/gemfast/gemfast.hcl delete mode 100644 omnibus/files/gemfast/gemfast.service delete mode 100644 omnibus/files/gemfast/gemfast_acl.csv delete mode 100755 omnibus/package-scripts/gemfast/postinst delete mode 100644 omnibus/package-scripts/gemfast/preinst diff --git a/.github/workflows/build-and-release.yaml b/.github/workflows/build-and-release.yaml deleted file mode 100644 index 81bef04..0000000 --- a/.github/workflows/build-and-release.yaml +++ /dev/null @@ -1,297 +0,0 @@ -name: Build & Release - -on: - workflow_dispatch: - push: - branches: [ main ] - tags: - - "v[0-9]+.[0-9]+.[0-9]+" - pull_request: - branches: [ main ] - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - GO_VERSION: 1.22.1 - RUBY_VERSION: 3.3.1 - BUNDLER_VERSION: 2.5.9 - -jobs: - build: - if: | - !contains(github.event.pull_request.labels.*.name, 'skip:ci') - name: "build" - runs-on: ubuntu-latest - env: - BUNDLE_GEMFILE: ${{ github.workspace }}/omnibus/Gemfile - steps: - - uses: actions/checkout@v3 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: ${{ env.GO_VERSION }} - - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - bundler: ${{ env.BUNDLER_VERSION}} - bundler-cache: true - - name: Unit test - run: | - sudo mkdir -p /opt/gemfast/etc/gemfast/ - sudo chown -R $USER: /opt/gemfast - make test - - name: Get version - id: get-version - run: | - v=$(cat VERSION) - echo "version=${v}" >> "$GITHUB_OUTPUT" - - name: Build omnibus package - run: | - sudo mkdir -p /var/cache/omnibus - sudo chown -R $USER: /var/cache/omnibus - cd omnibus - bundle exec omnibus build gemfast - sha512sum pkg/*.deb > "pkg/gemfast-${{ steps.get-version.outputs.VERSION }}-checksums.txt" - - name: Upload omnibus package - uses: actions/upload-artifact@v4 - with: - name: gemfast-omnibus - path: omnibus/pkg/ - if-no-files-found: error - - name: Build docker image - run: | - docker build -t server:${{ steps.get-version.outputs.VERSION }}-pre . - docker tag server:${{ steps.get-version.outputs.VERSION }}-pre server:latest - docker save server:latest > gemfast-${{ steps.get-version.outputs.VERSION }}-pre.tar - - name: Upload docker image - uses: actions/upload-artifact@v4 - with: - name: gemfast-docker - path: gemfast-${{ steps.get-version.outputs.VERSION }}-pre.tar - if-no-files-found: error - - smoke-test: - name: "smoke" - runs-on: ubuntu-latest - needs: build - strategy: - matrix: - pkg: [omnibus, docker] - steps: - - uses: actions/checkout@v3 - - uses: actions/checkout@v3 - with: - repository: rails/rails - path: clones/rails - - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - - uses: actions/download-artifact@v4 - with: - name: gemfast-${{ matrix.pkg }} - - name: Smoke test - run: ./scripts/run_smoke_tests.sh "${{ matrix.pkg }}" - env: - BUILD_TYPE: "${{ matrix.pkg }}" - - cve-test: - name: "cve" - runs-on: ubuntu-latest - needs: build - strategy: - matrix: - pkg: [omnibus, docker] - steps: - - uses: actions/checkout@v3 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - - uses: actions/download-artifact@v4 - with: - name: gemfast-${{ matrix.pkg }} - - name: CVE test - run: ./scripts/run_cve_tests.sh "${{ matrix.pkg }}" - env: - BUILD_TYPE: "${{ matrix.pkg }}" - - filter-test: - name: "filter" - runs-on: ubuntu-latest - needs: build - strategy: - matrix: - pkg: [omnibus, docker] - steps: - - uses: actions/checkout@v3 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - - uses: actions/download-artifact@v4 - with: - name: gemfast-${{ matrix.pkg }} - - name: Filter test - run: ./scripts/run_filter_tests.sh "${{ matrix.pkg }}" - env: - BUILD_TYPE: "${{ matrix.pkg }}" - - private-gems-test: - name: "private-gems" - runs-on: ubuntu-latest - needs: build - strategy: - matrix: - pkg: [omnibus, docker] - steps: - - uses: actions/checkout@v3 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - - uses: actions/download-artifact@v4 - with: - name: gemfast-${{ matrix.pkg }} - - name: Private gems test - run: ./scripts/run_private_gem_tests.sh "${{ matrix.pkg }}" - env: - BUILD_TYPE: "${{ matrix.pkg }}" - - auth-test: - name: "auth" - runs-on: ubuntu-latest - needs: build - strategy: - matrix: - pkg: [omnibus, docker] - steps: - - uses: actions/checkout@v3 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - - uses: actions/download-artifact@v4 - with: - name: gemfast-${{ matrix.pkg }} - - name: Private gems test - run: ./scripts/run_auth_tests.sh - env: - BUILD_TYPE: "${{ matrix.pkg }}" - - pre-release: - name: "pre-release" - permissions: write-all - if: ${{ github.ref == 'refs/heads/main' }} - runs-on: "ubuntu-latest" - needs: - - build - - smoke-test - - cve-test - - filter-test - - private-gems-test - - auth-test - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - uses: actions/download-artifact@v4 - with: - name: gemfast-omnibus - - uses: actions/download-artifact@v4 - with: - name: gemfast-docker - - name: Get version - id: get-version - run: | - v=$(cat VERSION) - echo "version=${v}" >> "$GITHUB_OUTPUT" - - name: Rename omnibus artifact - run: | - mv *.deb "gemfast-${{ steps.get-version.outputs.VERSION }}-pre-amd64.deb" - mv *.txt "gemfast-${{ steps.get-version.outputs.VERSION }}-pre-checksums.txt" - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Push docker image - run: | - docker load < gemfast-${{ steps.get-version.outputs.VERSION }}-pre.tar - docker tag server:latest ghcr.io/gemfast/server:${{ steps.get-version.outputs.VERSION }}-pre - docker push ghcr.io/gemfast/server:${{ steps.get-version.outputs.VERSION }}-pre - - name: Create pre-release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh release create --prerelease --generate-notes --title "${{ steps.get-version.outputs.VERSION }} Pre-Release" \ - "v${{ steps.get-version.outputs.VERSION }}-pre" \ - "gemfast-${{ steps.get-version.outputs.VERSION }}-pre-amd64.deb" \ - "gemfast-${{ steps.get-version.outputs.VERSION }}-pre-checksums.txt" - - tagged-release: - if: startsWith(github.ref, 'refs/tags/v') - name: "release" - permissions: write-all - runs-on: "ubuntu-latest" - needs: - - build - - smoke-test - - cve-test - - filter-test - - private-gems-test - - auth-test - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - uses: actions/download-artifact@v4 - with: - name: gemfast-omnibus - - uses: actions/download-artifact@v4 - with: - name: gemfast-docker - - name: Get version - id: get-version - run: | - v=$(cat VERSION) - echo "version=${v}" >> "$GITHUB_OUTPUT" - - name: Rename omnibus artifact - run: | - mv *.deb "gemfast-${{ steps.get-version.outputs.VERSION }}-amd64.deb" - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Push docker image - run: | - docker load < gemfast-${{ steps.get-version.outputs.VERSION }}-pre.tar - docker tag server:latest ghcr.io/gemfast/server:${{ steps.get-version.outputs.VERSION }} - docker push ghcr.io/gemfast/server:${{ steps.get-version.outputs.VERSION }} - docker tag ghcr.io/gemfast/server:${{ steps.get-version.outputs.VERSION }} ghcr.io/gemfast/server:latest - docker push ghcr.io/gemfast/server:latest - - name: Create release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh release create --latest --generate-notes --title "${{ steps.get-version.outputs.VERSION }}" \ - "v${{ steps.get-version.outputs.VERSION }}" \ - "gemfast-${{ steps.get-version.outputs.VERSION }}-amd64.deb" \ - "gemfast-${{ steps.get-version.outputs.VERSION }}-checksums.txt" - - cleanup: - runs-on: ubuntu-latest - needs: - - build - - smoke-test - - cve-test - - filter-test - - private-gems-test - - auth-test - - pre-release - - tagged-release - if: ${{ always() && !cancelled() && needs.build.result == 'success' }} - steps: - - uses: geekyeggo/delete-artifact@v5 - with: - name: gemfast-${{ matrix.pkg }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..bc40434 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,166 @@ +name: Build +run-name: Build - ${{ github.ref_name }} + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_call: + inputs: + ref: + required: false + type: string + default: ${{ github.ref }} + +jobs: + + build: + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.22' + - name: Set up ko + uses: ko-build/setup-ko@v0.9 + - name: Go format check + run: | + if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then + echo "Go code is not formatted, run 'make fmt' to format code." + exit 1; + fi + - name: Run unit tests + run: | + make test + - name: Run vet + run: | + make vet + - name: Run goreleaser + uses: goreleaser/goreleaser-action@v6 + with: + version: '~> v2' + args: release --skip validate --skip archive --clean --snapshot + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + KO_DOCKER_REPO: goreleaser.ko.local/gemfast + - name: Save docker image + run: | + docker save goreleaser.ko.local/gemfast/server:latest > gemfast-PR-${{ github.sha }}.tar + - name: Upload docker image + uses: actions/upload-artifact@v4 + with: + name: gemfast-docker + path: gemfast-PR-${{ github.sha }}.tar + if-no-files-found: error + + smoke-test: + name: "smoke" + runs-on: ubuntu-latest + needs: build + strategy: + matrix: + pkg: [docker] + steps: + - uses: actions/checkout@v3 + - uses: actions/checkout@v3 + with: + repository: rails/rails + path: clones/rails + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + - uses: actions/download-artifact@v4 + with: + name: gemfast-${{ matrix.pkg }} + - name: Smoke test + run: ./scripts/run_smoke_tests.sh "${{ matrix.pkg }}" + env: + BUILD_TYPE: "${{ matrix.pkg }}" + + cve-test: + name: "cve" + runs-on: ubuntu-latest + needs: build + strategy: + matrix: + pkg: [docker] + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + - uses: actions/download-artifact@v4 + with: + name: gemfast-${{ matrix.pkg }} + - name: CVE test + run: ./scripts/run_cve_tests.sh "${{ matrix.pkg }}" + env: + BUILD_TYPE: "${{ matrix.pkg }}" + + filter-test: + name: "filter" + runs-on: ubuntu-latest + needs: build + strategy: + matrix: + pkg: [docker] + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + - uses: actions/download-artifact@v4 + with: + name: gemfast-${{ matrix.pkg }} + - name: Filter test + run: ./scripts/run_filter_tests.sh "${{ matrix.pkg }}" + env: + BUILD_TYPE: "${{ matrix.pkg }}" + + private-gems-test: + name: "private-gems" + runs-on: ubuntu-latest + needs: build + strategy: + matrix: + pkg: [docker] + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + - uses: actions/download-artifact@v4 + with: + name: gemfast-${{ matrix.pkg }} + - name: Private gems test + run: ./scripts/run_private_gem_tests.sh "${{ matrix.pkg }}" + env: + BUILD_TYPE: "${{ matrix.pkg }}" + + auth-test: + name: "auth" + runs-on: ubuntu-latest + needs: build + strategy: + matrix: + pkg: [docker] + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + - uses: actions/download-artifact@v4 + with: + name: gemfast-${{ matrix.pkg }} + - name: Private gems test + run: ./scripts/run_auth_tests.sh + env: + BUILD_TYPE: "${{ matrix.pkg }}" diff --git a/.github/workflows/check-version.yaml b/.github/workflows/check-version.yaml deleted file mode 100644 index f475516..0000000 --- a/.github/workflows/check-version.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Check Version - -on: - pull_request: - types: [opened, reopened, edited, labeled, unlabeled, synchronize] - -jobs: - check-version: - name: "check version" - runs-on: ubuntu-latest - if: | - !contains(github.event.pull_request.labels.*.name, 'skip:version') - steps: - - uses: actions/checkout@v3 - - name: Check that VERSION has been modified - run: | - git fetch origin ${{ github.base_ref }} --depth 1 && \ - git diff remotes/origin/${{ github.base_ref }} --name-only | grep VERSION \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..786ca3f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,48 @@ +name: Release +run-name: Release - ${{ github.ref_name }} - ${{ github.sha }} + +on: + push: + tags: + - "v*" + +env: + GO_VERSION: 1.22 + +jobs: + + release: + runs-on: ubuntu-latest + + permissions: + contents: write + packages: write + attestations: write + id-token: write + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + - run: git fetch --prune --unshallow + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '${{ env.GO_VERSION }}' + - name: Set up ko + uses: ko-build/setup-ko@v0.9 + - name: Login to container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Run goreleaser + uses: goreleaser/goreleaser-action@v6 + with: + version: '~> v2' + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + KO_DOCKER_REPO: ghcr.io/gemfast \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0fae3c0..aed760f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ gemfast.db bin/gemfast-server omnibus/pkg tmp -!test/fixtures/spec/*.gem \ No newline at end of file +!test/fixtures/spec/*.gem +dist/ \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..c93ce2f --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,46 @@ +version: 2 + +project_name: gemfast-server + +before: + hooks: + - go mod tidy + +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + ignore: + - goos: darwin + goarch: amd64 + +kos: + - repositories: + - ghcr.io/gemfast + base_image: cgr.dev/chainguard/wolfi-base + base_import_paths: true + sbom: none + local_domain: "goreleaser.ko.local" + platforms: + - linux/amd64 + - linux/arm64 + bare: false + tags: + - "{{ .Tag }}" + - latest + +archives: + - formats: ["tar.gz"] + name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + +changelog: + sort: asc + use: github + filters: + exclude: + - "^scripts:" \ No newline at end of file diff --git a/VERSION b/VERSION deleted file mode 100644 index 524cb55..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.1.1 diff --git a/docker/omnibus/ubuntu/Dockerfile b/docker/omnibus/ubuntu/Dockerfile deleted file mode 100644 index eaf76e3..0000000 --- a/docker/omnibus/ubuntu/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -ARG OS_IMAGE=ubuntu:jammy - -FROM $OS_IMAGE - -LABEL maintainer="Greg Schofield " - -ARG GO_VERSION=1.19.3 - -RUN apt update -y && \ -DEBIAN_FRONTEND=noninteractive \ -apt-get install -y curl gcc file fakeroot && \ -curl -OL https://golang.org/dl/go$GO_VERSION.linux-arm64.tar.gz && \ -tar -C /usr/local -xzf go$GO_VERSION.linux-arm64.tar.gz - -RUN curl -fsSL https://omnitruck.chef.io/chef/install.sh | bash -s -- -c "stable" -P "omnibus-toolchain" - -ENV PATH /opt/omnibus-toolchain/bin:/opt/omnibus-toolchain/embedded/bin:/usr/local/go/bin:${PATH} -RUN echo "${PATH}" >> /etc/bash.bashrc -CMD ["bash"] diff --git a/omnibus/GEMFAST-EULA.md b/omnibus/GEMFAST-EULA.md deleted file mode 100644 index e69de29..0000000 diff --git a/omnibus/Gemfile b/omnibus/Gemfile deleted file mode 100644 index 3b0220f..0000000 --- a/omnibus/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source "https://rubygems.org" - -gem "omnibus", github: "chef/omnibus", branch: "main" -gem "omnibus-software", github: "chef/omnibus-software", branch: "main" diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock deleted file mode 100644 index 6dc4589..0000000 --- a/omnibus/Gemfile.lock +++ /dev/null @@ -1,136 +0,0 @@ -GIT - remote: https://github.com/chef/omnibus-software.git - revision: e3e8437cb89487d7830ff9a15f56bb98ba216875 - branch: main - specs: - omnibus-software (23.10.301) - omnibus (>= 9.0.0) - -GIT - remote: https://github.com/chef/omnibus.git - revision: 82dae896a066542f1b66dc866186f856f37e518e - branch: main - specs: - omnibus (9.0.23) - aws-sdk-s3 (~> 1.116.0) - chef-cleanroom (~> 1.0) - chef-utils (>= 15.4) - contracts (>= 0.16.0, < 0.17.0) - ffi-yajl (~> 2.2) - license_scout (~> 1.0) - mixlib-shellout (>= 2.0, < 4.0) - mixlib-versioning - ohai (>= 16, < 19) - pedump - rexml (~> 3.2) - ruby-progressbar (~> 1.7) - thor (>= 0.18, < 2.0) - -GEM - remote: https://rubygems.org/ - specs: - addressable (2.8.5) - public_suffix (>= 2.0.2, < 6.0) - awesome_print (1.9.2) - aws-eventstream (1.2.0) - aws-partitions (1.835.0) - aws-sdk-core (3.185.1) - aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.5) - jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.72.0) - aws-sdk-core (~> 3, >= 3.184.0) - aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.116.0) - aws-sdk-core (~> 3, >= 3.127.0) - aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.4) - aws-sigv4 (1.6.0) - aws-eventstream (~> 1, >= 1.0.2) - chef-cleanroom (1.0.5) - chef-config (18.3.0) - addressable - chef-utils (= 18.3.0) - fuzzyurl - mixlib-config (>= 2.2.12, < 4.0) - mixlib-shellout (>= 2.0, < 4.0) - tomlrb (~> 1.2) - chef-utils (18.3.0) - concurrent-ruby - citrus (3.0.2) - concurrent-ruby (1.2.2) - contracts (0.16.1) - ffi (1.16.3) - ffi-yajl (2.6.0) - libyajl2 (>= 1.2) - fuzzyurl (0.9.0) - iostruct (0.0.5) - ipaddress (0.8.3) - jmespath (1.6.2) - json (2.6.3) - libyajl2 (2.1.0) - license_scout (1.3.6) - ffi-yajl (~> 2.2) - mixlib-shellout (>= 2.2, < 4.0) - toml-rb (>= 1, < 3) - mixlib-cli (2.1.8) - mixlib-config (3.0.27) - tomlrb - mixlib-log (3.0.9) - mixlib-shellout (3.2.7) - chef-utils - mixlib-versioning (1.2.12) - multipart-post (2.3.0) - net-scp (4.0.0) - net-ssh (>= 2.6.5, < 8.0.0) - net-ssh (7.2.0) - ohai (18.1.3) - chef-config (>= 14.12, < 19) - chef-utils (>= 16.0, < 19) - ffi (~> 1.9) - ffi-yajl (~> 2.2) - ipaddress - mixlib-cli (>= 1.7.0) - mixlib-config (>= 2.0, < 4.0) - mixlib-log (>= 2.0.1, < 4.0) - mixlib-shellout (~> 3.2, >= 3.2.5) - plist (~> 3.1) - train-core - wmi-lite (~> 1.0) - pedump (0.6.6) - awesome_print - iostruct (>= 0.0.4) - multipart-post (>= 2.0.0) - rainbow - zhexdump (>= 0.0.2) - plist (3.7.0) - public_suffix (5.0.3) - rainbow (3.1.1) - rexml (3.2.8) - strscan (>= 3.0.9) - ruby-progressbar (1.13.0) - strscan (3.1.0) - thor (1.2.2) - toml-rb (2.2.0) - citrus (~> 3.0, > 3.0) - tomlrb (1.3.0) - train-core (3.10.8) - addressable (~> 2.5) - ffi (!= 1.13.0) - json (>= 1.8, < 3.0) - mixlib-shellout (>= 2.0, < 4.0) - net-scp (>= 1.2, < 5.0) - net-ssh (>= 2.9, < 8.0) - wmi-lite (1.0.7) - zhexdump (0.0.2) - -PLATFORMS - ruby - -DEPENDENCIES - omnibus! - omnibus-software! - -BUNDLED WITH - 2.3.7 diff --git a/omnibus/config/projects/gemfast.rb b/omnibus/config/projects/gemfast.rb deleted file mode 100644 index ddfbce4..0000000 --- a/omnibus/config/projects/gemfast.rb +++ /dev/null @@ -1,20 +0,0 @@ -name "gemfast" -friendly_name "Gemfast Server" -maintainer "Greg Schofield " -homepage "https://www.gemfast.io" -license "Apache-2.0" - -build_iteration 1 -current_file ||= __FILE__ -version_file = File.expand_path("../../../../VERSION", current_file) -build_version IO.read(version_file).strip - -install_dir "#{default_root}/#{name}" - -dependency "gemfast" -dependency "caddy" - -package :deb do - compression_level 1 - compression_type :xz -end \ No newline at end of file diff --git a/omnibus/config/software/caddy.rb b/omnibus/config/software/caddy.rb deleted file mode 100644 index cfd54d1..0000000 --- a/omnibus/config/software/caddy.rb +++ /dev/null @@ -1,21 +0,0 @@ -name "caddy" -default_version "2.7.6" - -license "Apache-2.0" -skip_transitive_dependency_licensing true - -if arm? - version("2.7.6") { source sha512: "6513d40365c0570ff72c751db2d5f898d4ee9abe9241e73c3ad1062e21128745071b4efd3cc3443fc04fae2da49b69f06f70aadbe79d6a5327cc677fb86fb982" } - source url: "https://github.com/caddyserver/caddy/releases/download/v#{version}/caddy_#{version}_linux_arm64.tar.gz" -else - version("2.7.6") { source sha512: "b74311ec8263f30f6d36e5c8be151e8bc092b377789a55300d5671238b9043de5bd6db2bcefae32aa1e6fe94c47bbf02982c44a7871e5777b2596fdb20907cbf" } - source url: "https://github.com/caddyserver/caddy/releases/download/v#{version}/caddy_#{version}_linux_amd64.tar.gz" -end - -build do - mkdir "#{install_dir}/embedded/bin" - mkdir "#{install_dir}/etc/#{name}" - mkdir "#{install_dir}/systemd/#{name}" - copy "#{project_dir}/../gemfast/omnibus/files/#{name}/caddy.service", "#{install_dir}/systemd/#{name}" - copy "#{project_dir}/caddy", "#{install_dir}/embedded/bin" -end \ No newline at end of file diff --git a/omnibus/config/software/gemfast.rb b/omnibus/config/software/gemfast.rb deleted file mode 100644 index 0a8e8f3..0000000 --- a/omnibus/config/software/gemfast.rb +++ /dev/null @@ -1,31 +0,0 @@ -name "gemfast" -default_version "local_source" - -license "Apache-2.0" -skip_transitive_dependency_licensing true - -version("local_source") do - source path: "#{project.files_path}/../.." -end - -build do - env = with_standard_compiler_flags(with_embedded_path) - - make env: env - - mkdir "#{install_dir}/bin" - mkdir "#{install_dir}/embedded/bin" - mkdir "#{install_dir}/etc/#{name}" - mkdir "#{install_dir}/systemd/#{name}" - mkdir "#{install_dir}/share" - mkdir "#{install_dir}/default" - - %w(auth_model.conf gemfast_acl.csv).each do |f| - copy "#{project_dir}/omnibus/files/#{name}/#{f}", "#{install_dir}/etc/#{name}" - end - copy "#{project_dir}/omnibus/files/#{name}/gemfast.service", "#{install_dir}/systemd/#{name}" - copy "#{project_dir}/bin/#{name}-server", "#{install_dir}/embedded/bin" - copy "#{project_dir}/omnibus/files/gemfast/gemfast.hcl", "#{install_dir}/default" - - link "#{install_dir}/embedded/bin/#{name}-server", "#{install_dir}/bin/#{name}-server" -end \ No newline at end of file diff --git a/omnibus/files/caddy/caddy.service b/omnibus/files/caddy/caddy.service deleted file mode 100644 index cf2e814..0000000 --- a/omnibus/files/caddy/caddy.service +++ /dev/null @@ -1,39 +0,0 @@ -# caddy.service -# -# For using Caddy with a config file. -# -# Make sure the ExecStart and ExecReload commands are correct -# for your installation. -# -# See https://caddyserver.com/docs/install for instructions. -# -# WARNING: This service does not use the --resume flag, so if you -# use the API to make changes, they will be overwritten by the -# Caddyfile next time the service is restarted. If you intend to -# use Caddy's API to configure it, add the --resume flag to the -# `caddy run` command or use the caddy-api.service file instead. - -[Unit] -Description=Caddy -Documentation=https://caddyserver.com/docs/ -After=network.target network-online.target -Before=gemfast.service -Requires=network-online.target -PartOf=gemfast.service - -[Service] -Type=notify -User=gemfast -Group=gemfast -ExecStartPre=/opt/gemfast/bin/gemfast-server caddyfile -o /opt/gemfast/etc/caddy/Caddyfile -ExecStart=/opt/gemfast/embedded/bin/caddy run --environ --config /opt/gemfast/etc/caddy/Caddyfile -ExecReload=/opt/gemfast/embedded/bin/caddy reload --config /opt/gemfast/etc/caddy/Caddyfile --force -TimeoutStopSec=5s -LimitNOFILE=1048576 -LimitNPROC=512 -PrivateTmp=true -ProtectSystem=full -AmbientCapabilities=CAP_NET_BIND_SERVICE - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/omnibus/files/gemfast/auth_model.conf b/omnibus/files/gemfast/auth_model.conf deleted file mode 100644 index 3058f3a..0000000 --- a/omnibus/files/gemfast/auth_model.conf +++ /dev/null @@ -1,12 +0,0 @@ -[request_definition] -r = sub, obj, act - -[policy_definition] -p = sub, obj, act - -[policy_effect] -e = some(where (p.eft == allow)) - -[matchers] -m = r.sub == p.sub && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") - diff --git a/omnibus/files/gemfast/gemfast.hcl b/omnibus/files/gemfast/gemfast.hcl deleted file mode 100644 index 858de34..0000000 --- a/omnibus/files/gemfast/gemfast.hcl +++ /dev/null @@ -1,67 +0,0 @@ -# This is the configuration file for Gemfast Server. -# For documentation of all options, please visit https://gemfast.io/docs/configuration/ - -##### Server Settings ##### -# port = 2020 -# log_level = "info" -# dir = "/var/gemfast" -# gem_dir = "/var/gemfast/gems" -# db_dir = "/var/gemfast/db" -# private_gems_namespace = "private" -# ui_disabled = false -# trial_mode = false -# license_key = "foobar" - -##### Caddy Settings ##### -# caddy { -# admin_api_enabled = false -# metrics_disabled = false -# host = "localhost" -# port = 443 -# } - -##### Mirror Settings ##### -# mirror "https://rubygems.org" { -# enabled = true -# hostname = "rubygems.org" -# } - -##### Gem Filter Settings ##### -# filter { -# enabled = true -# action = "deny" -# regex = ["rails-.*"] -# } - -##### Gem CVE Settings ##### -# cve { -# enabled = true -# max_severity = "high" -# ruby_advisory_db_dir = "/opt/gemfast/share/ruby-advisory-db" -# } - -##### Authentication Settings ##### -# None Auth -# auth "none" {} -# -# Local Auth -# auth "local" { -# allow_anonymous_read = false -# admin_password = "password" -# user { -# username = "user1" -# password = "mypassword1" -# } -# user { -# username = "user2" -# password = "mypassword2" -# } -# } -# -# GitHub Auth -# auth "github" { -# allow_anonymous_read = false -# github_client_id = "foobar" -# github_client_secret = "foobar" -# github_user_orgs = ["myorg"] -# } \ No newline at end of file diff --git a/omnibus/files/gemfast/gemfast.service b/omnibus/files/gemfast/gemfast.service deleted file mode 100644 index 1fae42b..0000000 --- a/omnibus/files/gemfast/gemfast.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Gemfast Private Rubygems Server -Documentation=https://gemfast.io -After=network.target network-online.target caddy.service -Requires=caddy.service - -[Service] -Type=simple -User=gemfast -Group=gemfast -ExecStart=/opt/gemfast/bin/gemfast-server start -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/omnibus/files/gemfast/gemfast_acl.csv b/omnibus/files/gemfast/gemfast_acl.csv deleted file mode 100644 index 1a8f16d..0000000 --- a/omnibus/files/gemfast/gemfast_acl.csv +++ /dev/null @@ -1,10 +0,0 @@ -p, admin, /*, * -p, anonymous, /admin/api/v1/login, * -p, write, /admin/api/v1/refresh-token, * -p, write, /admin/api/v1/token, * -p, write, /admin/api/v1/*, GET -p, write, /private/*, * -p, read, /admin/api/v1/refresh-token, * -p, read, /admin/api/v1/token, * -p, read, /admin/api/v1/*, GET -p, read, /private/*, GET diff --git a/omnibus/package-scripts/gemfast/postinst b/omnibus/package-scripts/gemfast/postinst deleted file mode 100755 index 5464a33..0000000 --- a/omnibus/package-scripts/gemfast/postinst +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -PROGNAME=`basename $0` -error_exit() -{ - echo "${PROGNAME}: ${1:-"Unknown Error"}" 1>&2 - exit 1 -} - -set -eo pipefail - -id -u gemfast &>/dev/null || useradd -m -U gemfast -groupadd -f gemfast &>/dev/null -usermod -a -G gemfast gemfast -rm -f /usr/bin/gemfast -ln -sf /opt/gemfast/bin/gemfast-server /usr/bin || error_exit "Cannot link gemfast-server to /usr/bin" -mkdir -p /etc/gemfast -mkdir -p /var/gemfast/db - -if [ ! -f "/etc/gemfast/gemfast.hcl" ]; then - cp /opt/gemfast/default/gemfast.hcl /etc/gemfast -fi - -for d in "/var/gemfast" "/etc/gemfast" "/opt/gemfast" -do - chown -R gemfast:gemfast $d -done - -for sv in "caddy" "gemfast" -do - cp "/opt/gemfast/systemd/$sv/$sv.service" /etc/systemd/system - systemctl enable $sv -done - -echo "Thank you for installing Gemfast Server! For help getting started visit https://gemfast.io/docs/installation/" - -exit 0 \ No newline at end of file diff --git a/omnibus/package-scripts/gemfast/preinst b/omnibus/package-scripts/gemfast/preinst deleted file mode 100644 index 88db2f6..0000000 --- a/omnibus/package-scripts/gemfast/preinst +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -INSTALLER_DIR=/opt/gemfast -if [ -e $INSTALLER_DIR ]; then - echo "removing $INSTALLER_DIR..." - - # have to do this dance of moving /opt/gemfast to a tmp dir since files may be in use - tmp_dir="/opt/.gemfast.$$" - # if we can't create the tmp_dir then fail hard to prevent any possible security hole - (umask 077 && mkdir $tmp_dir) || exit 1 - # now we can clean up the tmp_dir we created safely - mv $INSTALLER_DIR $tmp_dir - # ignore errors which must be EBUSY issues, this may crate some litter, which may - # be unavoidable - rm -rf $tmp_dir || true -fi \ No newline at end of file From 3722304bb7c491d283cd57143a83088d59002cd7 Mon Sep 17 00:00:00 2001 From: Gregory Schofield Date: Wed, 9 Jul 2025 16:17:37 -0400 Subject: [PATCH 2/2] Remove caddy and all omnibus references. Signed-off-by: Gregory Schofield --- .github/workflows/build.yml | 10 ++- .gitignore | 4 +- Dockerfile | 25 ------- Makefile | 17 ++--- README.md | 39 ++++------ bin/.gitkeep | 1 - cmd/gemfast-server/caddyfile.go | 73 ------------------- cmd/gemfast-server/start.go | 7 ++ internal/config/config.go | 44 ++--------- internal/middleware/acl.go | 41 +++++++---- .../middleware/auth_model.conf | 0 .../middleware/gemfast_acl.csv | 0 scripts/_functions.sh | 2 +- scripts/run_auth_tests.sh | 26 +++---- scripts/run_cve_tests.sh | 6 +- scripts/run_filter_tests.sh | 12 +-- scripts/run_private_gem_tests.sh | 8 +- scripts/run_smoke_tests.sh | 14 ++-- scripts/upload_all.sh | 2 +- 19 files changed, 95 insertions(+), 236 deletions(-) delete mode 100644 Dockerfile delete mode 100644 bin/.gitkeep delete mode 100644 cmd/gemfast-server/caddyfile.go rename auth_model.conf => internal/middleware/auth_model.conf (100%) rename gemfast_acl.csv => internal/middleware/gemfast_acl.csv (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc40434..082e518 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,6 +15,10 @@ on: type: string default: ${{ github.ref }} +env: + GO_VERSION: '1.22' + RUBY_VERSION: '3.4' + jobs: build: @@ -28,7 +32,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: ${{ env.GO_VERSION }} - name: Set up ko uses: ko-build/setup-ko@v0.9 - name: Go format check @@ -50,10 +54,10 @@ jobs: args: release --skip validate --skip archive --clean --snapshot env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - KO_DOCKER_REPO: goreleaser.ko.local/gemfast + KO_DOCKER_REPO: goreleaser.ko.local - name: Save docker image run: | - docker save goreleaser.ko.local/gemfast/server:latest > gemfast-PR-${{ github.sha }}.tar + docker save goreleaser.ko.local/server:latest > gemfast-PR-${{ github.sha }}.tar - name: Upload docker image uses: actions/upload-artifact@v4 with: diff --git a/.gitignore b/.gitignore index aed760f..4530fab 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,8 @@ prerelease_specs* *.gem !test/fixtures/gem_list/*.gem gemfast.db -bin/gemfast-server omnibus/pkg tmp !test/fixtures/spec/*.gem -dist/ \ No newline at end of file +dist/ +bin/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 54c335f..0000000 --- a/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM golang:1.22 -LABEL org.opencontainers.image.source="https://github.com/gemfast/server" -WORKDIR /app - -COPY go.mod go.sum ./ -RUN go mod download - -ADD internal ./internal -ADD cmd ./cmd -ADD bin ./bin - -COPY *.go ./ -COPY Makefile ./ - -RUN mkdir -p /opt/gemfast/etc/gemfast && \ - mkdir -p /var/gemfast && \ - mkdir -p /etc/gemfast && \ - make - -COPY gemfast_acl.csv /opt/gemfast/etc/gemfast/ -COPY auth_model.conf /opt/gemfast/etc/gemfast/ - -EXPOSE 2020 - -CMD ["/app/bin/gemfast-server", "start"] \ No newline at end of file diff --git a/Makefile b/Makefile index 0bff803..38bf73d 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,19 @@ -.PHONY: all omnibus test clean +.PHONY: all test clean build: - go build -mod=mod - mv server bin/gemfast-server - chmod +x bin/gemfast-server - -omnibus: - cd omnibus && bundle install - cd omnibus && bundle exec omnibus build gemfast + go build -o bin/gemfast-server main.go run: - go run -mod=mod main.go start + go run main.go start fmt: go fmt ./... test: - go test -mod=mod ./... + go test ./... + +vet: + go vet ./... clean: go clean diff --git a/README.md b/README.md index c6bf5e7..afc9f9b 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,8 @@ - [Gemfast](#gemfast) - [Why Gemfast](#why-gemfast) - [Installing](#installing) - - [Debian Package](#debian-package) - - [Debian Package SSL](#debian-package-ssl) - [Docker](#docker) + - [Prebuilt Binaries](#prebuilt-binaries) - [Building From Source](#building-from-source) - [Docs](#docs) - [UI](#ui) @@ -19,41 +18,23 @@ Gemfast was created for users who need to self-host their rubygems and want some Gemfast has the following unique benefits: -* Two installation methods: [Debian Package](#debian-package) and [Docker Image](#docker) +* Two installation methods: [Docker Image](#docker) or precompiled binaries * No need to install/upgrade/manage a version of Ruby on the server * No external server dependencies like postgres, redis or memcached -* Automatic HTTPS via Caddy * User login via GitHub oAuth -* No external server dependencies like postgres, redis or memcached * Allow/Deny gems based on CVE severity or a regex list using the [ruby-advisory-db](https://github.com/rubysec/ruby-advisory-db) -* Go is generally faster and requires less memory then Ruby (still :heart: Ruby though) +* Performance benefits of Go ## Installing -Gemfast is currently distributed in two different ways, a `.deb` package and a `docker` image. - -The `.deb` package includes a web server which proxies HTTPS traffic to Gemfast and is recommended when installing Gemfast on a virtual machine or bare-metal instance. - -### Debian Package - -To install the .deb package, download it from the latest GitHub release and install it with dpkg. - -```bash -curl -L -O gemfast__amd64.deb -sudo dpkg -i ./gemfast__amd64.deb -sudo systemctl start gemfast.service -``` - -#### Debian Package SSL - -The Gemfast `.deb` package includes Caddy Server which will automatically generate and manage a let's encrypt SSL certificate for your server. Caddy offers a few ways to generate a valid SSL certificate, see: https://caddyserver.com/docs/automatic-https#acme-challenges. If the let's encrypt challenge fails, the server will use a self-signed certificate. +Gemfast is currently distributed in two different ways, a `docker` image and precompiled binaries. ### Docker When running Gemfast as a container, its important to mount the following directories: -* /etc/gemfast - The directory for the gemfast.hcl config file * /var/gemfast - The directory for the Gemfast data including gems and database +* /etc/gemfast - The directory for the gemfast.hcl config file. It is possible to configure the config file path using `env GEMFAST_CONFIG_FILE=/path/to/my/file.hcl` ```bash docker run -d --name gemfast-server \ @@ -63,6 +44,16 @@ docker run -d --name gemfast-server \ ghcr.io/gemfast/server:latest ``` +### Prebuilt Binaries + +Currently Prebuild binaries are available on each GitHub release for the following platforms. + +- linux_amd64 +- linux_arm64 +- darwin_arm64 + +Simply download and extract the tarball to run the server. + ### Building From Source Gemfast uses Make to build binaries. To build and run a static binary: diff --git a/bin/.gitkeep b/bin/.gitkeep deleted file mode 100644 index 45adbb2..0000000 --- a/bin/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -.gitkeep \ No newline at end of file diff --git a/cmd/gemfast-server/caddyfile.go b/cmd/gemfast-server/caddyfile.go deleted file mode 100644 index d4dde7a..0000000 --- a/cmd/gemfast-server/caddyfile.go +++ /dev/null @@ -1,73 +0,0 @@ -package cmd - -import ( - "bytes" - "fmt" - "os" - "text/template" - - "github.com/gemfast/server/internal/config" - "github.com/rs/zerolog/log" - "github.com/spf13/cobra" -) - -const CaddyfileTemplate = `{{- if .AdminDisabled }}{ - admin off -} -{{- end }} -{{ .Host }}:{{ .Port }} { - encode zstd gzip - {{- if .MetricsEnabled }} - metrics /caddymetrics - {{- end }} - reverse_proxy :{{ .GemfastPort }} -} -` - -var caddyfileCmd = &cobra.Command{ - Use: "caddyfile", - Short: "Write the Caddy configuration file to stdout", - Long: "Reads the gemfast.hcl config file and outputs the Caddyfile to stdout or to an output file if specified.", - Run: func(cmd *cobra.Command, args []string) { - caddyfile() - }, -} - -var Output string - -func init() { - rootCmd.AddCommand(caddyfileCmd) - caddyfileCmd.Flags().StringVarP(&Output, "output", "o", "", "Location to write the Caddyfile to") -} - -func caddyfile() { - cfg := config.NewConfig() - m := make(map[string]interface{}) - m["Host"] = cfg.CaddyConfig.Host - m["Port"] = cfg.CaddyConfig.Port - m["GemfastPort"] = cfg.Port - if !cfg.CaddyConfig.AdminAPIEnabled { - m["AdminDisabled"] = true - } - if !cfg.CaddyConfig.MetricsDisabled { - m["MetricsEnabled"] = true - } - t, err := template.New("Caddyfile").Parse(CaddyfileTemplate) - if err != nil { - log.Fatal().Err(err).Msg("failed to parse Caddyfile template") - } - - var tpl bytes.Buffer - err = t.Execute(&tpl, m) - if err != nil { - log.Fatal().Err(err).Msg("failed to execute Caddyfile template") - } - if Output != "" { - err := os.WriteFile(Output, tpl.Bytes(), 0644) - if err != nil { - log.Fatal().Err(err).Msg("failed to write Caddyfile") - } - return - } - fmt.Println(tpl.String()) -} diff --git a/cmd/gemfast-server/start.go b/cmd/gemfast-server/start.go index 3d9c211..3b4e866 100644 --- a/cmd/gemfast-server/start.go +++ b/cmd/gemfast-server/start.go @@ -1,6 +1,7 @@ package cmd import ( + "os" "time" "github.com/gemfast/server/internal/api" @@ -22,11 +23,17 @@ var startCmd = &cobra.Command{ }, } +var configPath string + func init() { + startCmd.Flags().StringVarP(&configPath, "config", "c", "", "Path to the config file") rootCmd.AddCommand(startCmd) } func start() { + if configPath != "" { + os.Setenv("GEMFAST_CONFIG_FILE", configPath) + } // Load the config cfg := config.NewConfig() log.Info().Msg("starting services") diff --git a/internal/config/config.go b/internal/config/config.go index e453327..8128adf 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -24,19 +24,11 @@ type Config struct { UIDisabled bool `hcl:"ui_disabled,optional"` MetricsDisabled bool `hcl:"metrics_disabled,optional"` - LicenseKey string `hcl:"license_key,optional"` - CaddyConfig *CaddyConfig `hcl:"caddy,block"` - Mirrors []*MirrorConfig `hcl:"mirror,block"` - Filter *FilterConfig `hcl:"filter,block"` - CVE *CVEConfig `hcl:"cve,block"` - Auth *AuthConfig `hcl:"auth,block"` -} - -type CaddyConfig struct { - AdminAPIEnabled bool `hcl:"admin_api_enabled,optional"` - MetricsDisabled bool `hcl:"metrics_disabled,optional"` - Host string `hcl:"host,optional"` - Port int `hcl:"port,optional"` + LicenseKey string `hcl:"license_key,optional"` + Mirrors []*MirrorConfig `hcl:"mirror,block"` + Filter *FilterConfig `hcl:"filter,block"` + CVE *CVEConfig `hcl:"cve,block"` + Auth *AuthConfig `hcl:"auth,block"` } type MirrorConfig struct { @@ -114,7 +106,6 @@ func NewConfig() *Config { func (c *Config) setDefaultConfig() { c.setDefaultServerConfig() - c.setDefaultCaddyConfig() c.setDefaultMirrorConfig() c.setDefaultAuthConfig() c.setDefaultFilterConfig() @@ -142,25 +133,6 @@ func (c *Config) setDefaultServerConfig() { c.PrivateGemsNamespace = "private" } } - -func (c *Config) setDefaultCaddyConfig() { - if c.CaddyConfig == nil { - c.CaddyConfig = &CaddyConfig{ - AdminAPIEnabled: false, - MetricsDisabled: false, - Host: "https://localhost", - Port: 443, - } - return - } - if c.CaddyConfig.Port == 0 { - c.CaddyConfig.Port = 443 - } - if c.CaddyConfig.Host == "" { - c.CaddyConfig.Host = fmt.Sprintf("https://localhost:%d", c.CaddyConfig.Port) - } -} - func configureLogLevel(ll string) { level, err := zerolog.ParseLevel(ll) if err != nil { @@ -221,7 +193,7 @@ func readJWTSecretKeyFromPath(keyPath string) string { } func (c *Config) setDefaultAuthConfig() { - defaultJWTSecretKeyPath := "/opt/gemfast/etc/gemfast/.jwt_secret_key" + defaultJWTSecretKeyPath := ".jwt_secret_key" if c.Auth == nil { c.Auth = &AuthConfig{ Type: "local", @@ -272,7 +244,7 @@ func (c *Config) setDefaultCVEConfig() { c.CVE = &CVEConfig{ Enabled: false, MaxSeverity: "high", - RubyAdvisoryDBDir: "/opt/gemfast/share/ruby-advisory-db", + RubyAdvisoryDBDir: "ruby-advisory-db", } return } @@ -280,6 +252,6 @@ func (c *Config) setDefaultCVEConfig() { c.CVE.MaxSeverity = "high" } if c.CVE.RubyAdvisoryDBDir == "" { - c.CVE.RubyAdvisoryDBDir = "/opt/gemfast/share/ruby-advisory-db" + c.CVE.RubyAdvisoryDBDir = "ruby-advisory-db" } } diff --git a/internal/middleware/acl.go b/internal/middleware/acl.go index 8356b79..d33e541 100644 --- a/internal/middleware/acl.go +++ b/internal/middleware/acl.go @@ -1,15 +1,22 @@ package middleware import ( + _ "embed" "fmt" + "os" "path/filepath" "github.com/casbin/casbin/v2" "github.com/gemfast/server/internal/config" - u "github.com/gemfast/server/internal/utils" "github.com/rs/zerolog/log" ) +//go:embed auth_model.conf +var embeddedAuthModel []byte + +//go:embed gemfast_acl.csv +var embeddedACL []byte + type ACL struct { casbin *casbin.Enforcer cfg *config.Config @@ -26,12 +33,9 @@ func NewACL(cfg *config.Config) *ACL { log.Fatal().Err(err).Msg("failed to get absolute path for acl") } } else { - for _, path := range []string{"/opt/gemfast/etc/gemfast/gemfast_acl.csv", "gemfast_acl.csv"} { - exists, _ := u.FileExists(path) - if exists { - policyPath = path - break - } + policyPath, err = writeTempFile("gemfast_acl.csv", embeddedACL) + if err != nil { + log.Fatal().Err(err).Msg("failed to write embedded acl to temp file") } } @@ -41,12 +45,9 @@ func NewACL(cfg *config.Config) *ACL { log.Fatal().Err(err).Msg("failed to get absolute path for auth_model") } } else { - for _, path := range []string{"/opt/gemfast/etc/gemfast/auth_model.conf", "auth_model.conf"} { - exists, _ := u.FileExists(path) - if exists { - authPath = path - break - } + authPath, err = writeTempFile("auth_model.conf", embeddedAuthModel) + if err != nil { + log.Fatal().Err(err).Msg("failed to write embedded auth model to temp file") } } @@ -56,12 +57,22 @@ func NewACL(cfg *config.Config) *ACL { acl, err := casbin.NewEnforcer(authPath, policyPath) if err != nil { log.Fatal().Err(err).Msg("failed to initialize the acl") - } else { - log.Info().Str("detail", policyPath).Msg("successfully initialized ACL enforcer") } + log.Info().Str("detail", policyPath).Msg("successfully initialized ACL enforcer") + return &ACL{casbin: acl, cfg: cfg} } +func writeTempFile(name string, content []byte) (string, error) { + tmp, err := os.CreateTemp("", name) + if err != nil { + return "", err + } + defer tmp.Close() + _, err = tmp.Write(content) + return tmp.Name(), err +} + func (acl *ACL) Enforce(role string, path string, method string) (bool, error) { return acl.casbin.Enforce(role, path, method) } diff --git a/auth_model.conf b/internal/middleware/auth_model.conf similarity index 100% rename from auth_model.conf rename to internal/middleware/auth_model.conf diff --git a/gemfast_acl.csv b/internal/middleware/gemfast_acl.csv similarity index 100% rename from gemfast_acl.csv rename to internal/middleware/gemfast_acl.csv diff --git a/scripts/_functions.sh b/scripts/_functions.sh index a6ddd60..0f2d6f5 100644 --- a/scripts/_functions.sh +++ b/scripts/_functions.sh @@ -4,7 +4,7 @@ function start_server() { local BUILD_TYPE="$1" if [[ "$BUILD_TYPE" == "docker" ]]; then docker load -i gemfast*.tar - docker run -d --name gemfast-server -p 80:2020 -v /etc/gemfast:/etc/gemfast -v /var/gemfast:/var/gemfast -v /etc/machine-id:/etc/machine-id server:latest + docker run -d --name gemfast-server -p 2020:2020 -v /etc/gemfast:/etc/gemfast -v /var/gemfast:/var/gemfast goreleaser.ko.local/server:latest start sleep 5 docker ps docker logs gemfast-server diff --git a/scripts/run_auth_tests.sh b/scripts/run_auth_tests.sh index aa2e318..799282d 100755 --- a/scripts/run_auth_tests.sh +++ b/scripts/run_auth_tests.sh @@ -14,10 +14,6 @@ sudo mkdir -p /var/gemfast sudo chown -R $USER: /etc/gemfast sudo chown -R $USER: /var/gemfast cat << CONFIG > /etc/gemfast/gemfast.hcl -caddy { - port = 80 - host = "http://localhost" -} license_key = "B7D865-DA12D3-11DA3D-DD81AE-9420D3-V3" auth "local" { allow_anonymous_read = false @@ -32,10 +28,10 @@ CONFIG start_server "$BUILD_TYPE" -jwt=$(curl -s -X POST -H "Content-Type: application/json" http://localhost:80/admin/api/v1/login -d '{"username": "admin", "password":"foobar"}' | jq -r .token) -token=$(curl -s -X POST -H "Authorization: Bearer $jwt" -H "Content-Type: application/json" http://localhost:80/admin/api/v1/token | jq -r .token) -bvjwt=$(curl -s -X POST -H "Content-Type: application/json" http://localhost:80/admin/api/v1/login -d '{"username": "bobvance", "password":"mypassword"}' | jq -r .token) -bvtoken=$(curl -s -X POST -H "Authorization: Bearer $bvjwt" -H "Content-Type: application/json" http://localhost:80/admin/api/v1/token | jq -r .token) +jwt=$(curl -s -X POST -H "Content-Type: application/json" http://localhost:2020/admin/api/v1/login -d '{"username": "admin", "password":"foobar"}' | jq -r .token) +token=$(curl -s -X POST -H "Authorization: Bearer $jwt" -H "Content-Type: application/json" http://localhost:2020/admin/api/v1/token | jq -r .token) +bvjwt=$(curl -s -X POST -H "Content-Type: application/json" http://localhost:2020/admin/api/v1/login -d '{"username": "bobvance", "password":"mypassword"}' | jq -r .token) +bvtoken=$(curl -s -X POST -H "Authorization: Bearer $bvjwt" -H "Content-Type: application/json" http://localhost:2020/admin/api/v1/token | jq -r .token) mkdir ./test-vendor pushd test-vendor @@ -57,7 +53,7 @@ pushd vendor/cache for gem in *.gem; do [ -f "$gem" ] || break echo "Uploading $gem" - gem push "$gem" --host http://localhost:80/private -k gemfast + gem push "$gem" --host http://localhost:2020/private -k gemfast done sleep 5 @@ -76,11 +72,11 @@ cd test-private-gems # admin user cat << CONFIG > Gemfile -source "http://localhost:80/private" +source "http://localhost:2020/private" gem "rails" CONFIG -bundle config http://localhost:80/private/ "admin:$token" +bundle config http://localhost:2020/private/ "admin:$token" bundle # unauthorized user @@ -92,11 +88,11 @@ bundle clean --force sudo rm -f Gemfile Gemfile.lock cat << CONFIG > Gemfile -source "http://localhost:80/private" +source "http://localhost:2020/private" gem "rails" CONFIG -bundle config http://localhost:80/private/ "noauth:faketoken" +bundle config http://localhost:2020/private/ "noauth:faketoken" if [[ $(bundle 2>&1 | grep "Access token could not be authenticated") ]]; then echo "gemfast is blocking unauthenticated access" else @@ -113,9 +109,9 @@ bundle clean --force sudo rm -f Gemfile Gemfile.lock cat << CONFIG > Gemfile -source "http://localhost:80/private" +source "http://localhost:2020/private" gem "rails" CONFIG -bundle config http://localhost:80/private/ "bobvance:$bvtoken" +bundle config http://localhost:2020/private/ "bobvance:$bvtoken" bundle \ No newline at end of file diff --git a/scripts/run_cve_tests.sh b/scripts/run_cve_tests.sh index 7df4022..91dbe4b 100755 --- a/scripts/run_cve_tests.sh +++ b/scripts/run_cve_tests.sh @@ -12,10 +12,6 @@ gem update --system sudo mkdir -p /etc/gemfast sudo chown -R $USER: /etc/gemfast cat << CONFIG > /etc/gemfast/gemfast.hcl -caddy { - port = 80 - host = "http://localhost" -} license_key = "B7D865-DA12D3-11DA3D-DD81AE-9420D3-V3" auth "none" {} cve { @@ -34,7 +30,7 @@ source "https://rubygems.org" gem "activerecord", "4.2.0" CONFIG -bundle config mirror.https://rubygems.org http://localhost +bundle config mirror.https://rubygems.org http://localhost:2020 if [[ $(bundle 2>&1 | grep "405") ]]; then echo "cve is blocking activerecord 4.2.0" else diff --git a/scripts/run_filter_tests.sh b/scripts/run_filter_tests.sh index a4385e9..c8ea72a 100755 --- a/scripts/run_filter_tests.sh +++ b/scripts/run_filter_tests.sh @@ -12,10 +12,6 @@ gem update --system sudo mkdir -p /etc/gemfast sudo chown -R $USER: /etc/gemfast cat << CONFIG > /etc/gemfast/gemfast.hcl -caddy { - port = 80 - host = "http://localhost" -} license_key = "B7D865-DA12D3-11DA3D-DD81AE-9420D3-V3" auth "none" {} filter { @@ -35,17 +31,13 @@ source "https://rubygems.org" gem "stringio", "~> 3.0", ">= 3.0.7" CONFIG -bundle config mirror.https://rubygems.org http://localhost +bundle config mirror.https://rubygems.org http://localhost:2020 bundle popd sudo rm -rf /etc/gemfast/gemfast.hcl sudo tee /etc/gemfast/gemfast.hcl > /dev/null <<'CONFIG' -caddy { - port = 80 - host = "http://localhost" -} license_key = "B7D865-DA12D3-11DA3D-DD81AE-9420D3-V3" auth "none" {} filter { @@ -66,7 +58,7 @@ source "https://rubygems.org" gem "activesupport", "~> 7.0", ">= 7.0.5" CONFIG -bundle config mirror.https://rubygems.org http://localhost +bundle config mirror.https://rubygems.org http://localhost:2020 if [[ $(bundle 2>&1 | grep "405") ]]; then echo "gemfast is filtering activesupport 7.0.5" else diff --git a/scripts/run_private_gem_tests.sh b/scripts/run_private_gem_tests.sh index d3fe4b0..ba09209 100755 --- a/scripts/run_private_gem_tests.sh +++ b/scripts/run_private_gem_tests.sh @@ -12,10 +12,6 @@ gem update --system sudo mkdir -p /etc/gemfast sudo chown -R $USER: /etc/gemfast cat << CONFIG > /etc/gemfast/gemfast.hcl -caddy { - port = 80 - host = "http://localhost" -} license_key = "B7D865-DA12D3-11DA3D-DD81AE-9420D3-V3" auth "none" {} private_gems_namespace = "foobar" @@ -43,7 +39,7 @@ pushd vendor/cache for gem in *.gem; do [ -f "$gem" ] || break echo "Uploading $gem" - gem push "$gem" --host http://localhost:80/foobar -k gemfast + gem push "$gem" --host http://localhost:2020/foobar -k gemfast done sleep 5 @@ -61,7 +57,7 @@ mkdir ./test-private-gems cd test-private-gems cat << CONFIG > Gemfile -source "http://localhost:80/foobar" +source "http://localhost:2020/foobar" gem "rails" CONFIG bundle diff --git a/scripts/run_smoke_tests.sh b/scripts/run_smoke_tests.sh index 11bb120..80b7334 100755 --- a/scripts/run_smoke_tests.sh +++ b/scripts/run_smoke_tests.sh @@ -12,10 +12,6 @@ gem update --system sudo mkdir -p /etc/gemfast sudo chown -R $USER: /etc/gemfast cat << CONFIG > /etc/gemfast/gemfast.hcl -caddy { - port = 80 - host = "http://localhost" -} license_key = "B7D865-DA12D3-11DA3D-DD81AE-9420D3-V3" auth "none" {} CONFIG @@ -25,11 +21,11 @@ start_server "$BUILD_TYPE" cd ./clones pushd rails -bundle config mirror.https://rubygems.org http://localhost +bundle config mirror.https://rubygems.org http://localhost:2020 bundle -numGems=$(curl -s http://localhost/admin/api/v1/stats/bucket | jq -r '.gems.KeyN') -curl -s http://localhost/admin/api/v1/backup > gemfast.db +numGems=$(curl -s http://localhost:2020/admin/api/v1/stats/bucket | jq -r '.gems.KeyN') +curl -s http://localhost:2020/admin/api/v1/backup > gemfast.db sudo rm -rf /var/gemfast/db/gemfast.db sudo mv ./gemfast.db /var/gemfast/db/gemfast.db @@ -40,13 +36,13 @@ fi restart_server "$BUILD_TYPE" -numGemsBackup=$(curl -s http://localhost/admin/api/v1/stats/bucket | jq -r '.gems.KeyN') +numGemsBackup=$(curl -s http://localhost:2020/admin/api/v1/stats/bucket | jq -r '.gems.KeyN') if [ "$numGems" != "$numGemsBackup" ]; then echo "Number of gems in backup ($numGemsBackup) does not match number of gems in original ($numGems)" exit 1 fi -metrics=$(curl -s http://localhost/metrics | grep "gemfast") +metrics=$(curl -s http://localhost:2020/metrics | grep "gemfast") if [[ $metrics == "" ]] ; then echo "Metrics endpoint is not working" exit 1 diff --git a/scripts/upload_all.sh b/scripts/upload_all.sh index 55fea7c..5ec5af1 100755 --- a/scripts/upload_all.sh +++ b/scripts/upload_all.sh @@ -6,5 +6,5 @@ cd $gems_dir for gem in *.gem; do [ -f "$gem" ] || break echo "Uploading $gem" - gem push "$gem" --host http://localhost:8080 -k gemfast + gem push "$gem" --host http://localhost:2020 -k gemfast done \ No newline at end of file