name: CI on: push: branches: [ main ] pull_request: branches: [ main ] env: NOMAD_VERSION: '1.8.0' CNI_VERSION: '1.5.0' jobs: compile: runs-on: ubuntu-latest env: CGO_ENABLED: 0 # Enable additional processor optimizations: https://golang.org/wiki/MinimumRequirements#amd64 GOAMD64: v3 steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Update last trim for Go build cache # Go usually trims all builds not used for at least five days. We simulate that the last trim just occurred recently. # Otherwise, the cache restored in the previous step would not be used for the build resulting in a longer workflow run. # More details: https://github.com/golang/go/blob/d60ad1e068263832c711aaf17b6ccb1b7f71b000/src/cmd/go/internal/cache/cache.go#L255-L326 run: date +%s > ~/.cache/go-build/trim.txt continue-on-error: true - name: Build run: make build-cover - name: Upload Poseidon binary uses: actions/upload-artifact@v4 with: name: poseidon path: poseidon lint: name: lint runs-on: ubuntu-latest permissions: # Required: allow read access to the content for analysis. contents: read # Optional: allow read access to pull request. Use with `only-new-issues` option. pull-requests: read # Optional: Allow write access to checks to allow the action to annotate code in the PR. checks: write steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: version: latest args: --timeout=3m # We rely on the setup-go action to cache the Go pkg and build directories. skip-pkg-cache: true skip-build-cache: true test: runs-on: ubuntu-latest needs: [ compile ] steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Update last trim for Go build cache # Go usually trims all builds not used for at least five days. We simulate that the last trim just occurred recently. # Otherwise, the cache restored in the previous step would not be used for the build resulting in a longer workflow run. # More details: https://github.com/golang/go/blob/d60ad1e068263832c711aaf17b6ccb1b7f71b000/src/cmd/go/internal/cache/cache.go#L255-L326 run: date +%s > ~/.cache/go-build/trim.txt continue-on-error: true - name: Run tests run: make coverhtml - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4 if: ${{ success() || failure() }} with: token: ${{ secrets.CODECOV_TOKEN }} - name: Upload coverage report uses: actions/upload-artifact@v4 if: ${{ success() || failure() }} with: name: coverage_unit path: coverage/coverage_unit.html dep-scan: runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write needs: [ compile ] if: github.event_name != 'push' || github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' && github.actor != 'dependabot' steps: - name: Checkout code uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner in repo mode uses: aquasecurity/trivy-action@master with: scan-type: 'fs' format: 'template' template: '@/contrib/sarif.tpl' output: 'trivy-results.sarif' severity: 'HIGH,CRITICAL' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif' e2e-test: runs-on: ubuntu-latest needs: [ compile, test ] env: POSEIDON_AWS_ENDPOINT: ${{ secrets.POSEIDON_AWS_ENDPOINT }} steps: - name: Checkout repository uses: actions/checkout@v4 - name: Write secrets to environment file run: cat ./.github/workflows/resources/.env | envsubst > ./.env - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Update last trim for Go build cache # Go usually trims all builds not used for at least five days. We simulate that the last trim just occurred recently. # Otherwise, the cache restored in the previous step would not be used for the build resulting in a longer workflow run. # More details: https://github.com/golang/go/blob/d60ad1e068263832c711aaf17b6ccb1b7f71b000/src/cmd/go/internal/cache/cache.go#L255-L326 run: date +%s > ~/.cache/go-build/trim.txt continue-on-error: true - name: Cache Nomad and CNI binaries uses: actions/cache@v4 with: path: | ${{ github.workspace }}/nomad ${{ github.workspace }}/cni/bin key: ${{ runner.os }}-nomad-${{ env.NOMAD_VERSION }} restore-keys: | ${{ runner.os }}-nomad-${{ env.NOMAD_VERSION }} - name: Download Nomad binary run: | if [[ -f ./nomad ]]; then exit 0; fi wget -q "https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_linux_amd64.zip" wget -q "https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_SHA256SUMS" grep "nomad_${NOMAD_VERSION}_linux_amd64.zip" nomad_${NOMAD_VERSION}_SHA256SUMS | sha256sum -c - unzip nomad_${NOMAD_VERSION}_linux_amd64.zip - name: Download CNI binaries run: | if [[ -f ./cni/bin ]]; then exit 0; fi wget -q "https://github.com/containernetworking/plugins/releases/download/v${CNI_VERSION}/cni-plugins-linux-amd64-v${CNI_VERSION}.tgz" wget -q "https://github.com/containernetworking/plugins/releases/download/v${CNI_VERSION}/cni-plugins-linux-amd64-v${CNI_VERSION}.tgz.sha256" grep "cni-plugins-linux-amd64-v${CNI_VERSION}.tgz" cni-plugins-linux-amd64-v${CNI_VERSION}.tgz.sha256 | sha256sum -c - mkdir -p ./cni/bin tar zxvf cni-plugins-linux-amd64-v${CNI_VERSION}.tgz -C ./cni/bin - name: Set Nomad Config run: | cp ./docs/resources/secure-bridge.conflist ./cni/secure-bridge.conflist echo "server { default_scheduler_config { memory_oversubscription_enabled = true } }, client { cni_path = \"${{ github.workspace }}/cni/bin\", cni_config_dir = \"${{ github.workspace }}/cni\" }" > e2e-config.hcl - name: Download Poseidon binary uses: actions/download-artifact@v4 with: name: poseidon - name: Get current branch name id: branch-name uses: tj-actions/branch-names@v8 - name: Checkout matching branch for Dockerfiles (optional) id: checkout-dockerfiles if: steps.branch-name.outputs.is_default == 'false' uses: actions/checkout@v4 continue-on-error: true with: repository: openHPI/dockerfiles path: deploy/dockerfiles ref: ${{ steps.branch-name.outputs.current_branch }} - name: Build new e2e test image (optional) if: steps.checkout-dockerfiles.outcome == 'success' run: make e2e-test-docker-image - name: Run e2e tests run: | export $(cat ./.env | xargs) sudo ./nomad agent -dev -log-level=WARN -config e2e-config.hcl & until curl -s --fail http://localhost:4646/v1/agent/health ; do sleep 1; done chmod +x ./poseidon mkdir -p ${GOCOVERDIR} ./poseidon | tee poseidon.log & until curl -s --fail http://localhost:7200/api/v1/health ; do sleep 1; done make e2e-test if: ${{ success() || failure() }} - name: Setup Poseidon Socket run: | export $(cat ./.env | xargs) killall poseidon mkdir -p ~/.config/systemd/user cp ./.github/workflows/resources/poseidon-minimal.socket ~/.config/systemd/user/poseidon.socket cat ./.github/workflows/resources/poseidon-minimal.service | envsubst > ~/.config/systemd/user/poseidon.service echo "POSEIDON_SERVER_SYSTEMDSOCKETACTIVATION=TRUE" >> ./.env systemctl --user daemon-reload systemctl --user start poseidon.socket if: ${{ success() || failure() }} - name: Print Poseidon Failure logs if: failure() run: journalctl --user -xen --no-pager - name: Run e2e recovery tests run: make e2e-test-recovery if: ${{ success() || failure() }} - name: Print Systemd Failure logs run: | /usr/bin/systemctl --user show poseidon.service -p NRestarts journalctl --user -xe -u poseidon.service --no-pager if: failure() - name: Stop Poseidon to flush the coverage file run: systemctl --user stop poseidon.service poseidon.socket if: ${{ success() || failure() }} - name: Convert coverage reports run: make convert-run-coverage if: ${{ success() || failure() }} - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4 if: ${{ success() || failure() }} with: token: ${{ secrets.CODECOV_TOKEN }} - name: Upload coverage report uses: actions/upload-artifact@v4 if: ${{ success() || failure() }} with: name: coverage_run path: coverage/coverage_run.html