diff --git a/.github/workflows/build-pprd.yml b/.github/workflows/build-pprd.yml index 2612c86c..6cf9834e 100644 --- a/.github/workflows/build-pprd.yml +++ b/.github/workflows/build-pprd.yml @@ -6,7 +6,6 @@ on: - pprd - epic/v3 - any/branch-you-want - - fix/docs_dir-not-set jobs: docker: diff --git a/.github/workflows/build-preview.yml b/.github/workflows/build-preview.yml deleted file mode 100644 index ee139b8f..00000000 --- a/.github/workflows/build-preview.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: ❌ DS User Guide Previews - -on: - workflow_dispatch: - push: - branches: - - '*' - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - push: true - tags: designsafeci/ds-use-case-template:latest - - - name: Post build status in slack - id: slack - uses: slackapi/slack-github-action@v1.18.0 - with: - # This data can be any valid JSON from a previous step in the GitHub Action - payload: | - { - "build_status": "${{ job.status }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.github/workflows/requirements-validate.yml b/.github/workflows/requirements-validate.yml new file mode 100644 index 00000000..de140da0 --- /dev/null +++ b/.github/workflows/requirements-validate.yml @@ -0,0 +1,41 @@ +# Humans should not manage requirements.txt (bots do) +name: Validate requirements.txt not changed by human + +on: + pull_request: + paths: ['requirements.txt'] + types: [opened, synchronize, reopened] + +jobs: + reject-requirements-drift: + runs-on: ubuntu-latest + + # Skip if the last commit was from the bot (prevent unnecessary check) + if: github.event.head_commit.author.name != 'github-actions[bot]' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # full history + + - name: Check if requirements.txt was modified unexpectedly + run: | + # For PRs, check against base branch + # For pushes, check last commit + if [ "${{ github.event_name }}" = "pull_request" ]; then + BASE_REF="${{ github.event.pull_request.base.sha }}" + COMPARE_RANGE="$BASE_REF...HEAD" + else + COMPARE_RANGE="HEAD~1..HEAD" + fi + + # If requirements.txt modified in that range + if git diff --name-only $COMPARE_RANGE | grep -q "^requirements.txt$"; then + echo "::error::You may NOT edit 'requirements.txt'" + echo "::warning::Undo your changes to requirements.txt, so robot can maintain it." + echo "::notice::To pin dependencies, use 'poetry add '." + exit 1 + fi + + echo "'requirements.txt' unchanged (or only changed by bot)" diff --git a/.github/workflows/requirments-sync.yml b/.github/workflows/requirments-sync.yml new file mode 100644 index 00000000..2c38f60f --- /dev/null +++ b/.github/workflows/requirments-sync.yml @@ -0,0 +1,85 @@ +# Netlify requires requirements.txt (humans do not) +name: Sync requirements.txt with pyproject.toml + +on: + pull_request: + paths: ['pyproject.toml'] + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + detect-requirements-delta: + runs-on: ubuntu-latest + outputs: + has_change: ${{ steps.detect.outputs.has_change }} + + # Skip if the last commit was from the bot (prevent infinite loops) + if: github.event.head_commit.author.name != 'github-actions[bot]' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref || github.ref_name }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: 'pyproject.toml' + + - name: Install Poetry + run: pip install poetry + + - name: Detect whether requirements.txt has change + id: detect + run: | + output=$(make requirements.txt 2>&1) + echo "$output" + + # Check whether Make output suggests file is up to date + if echo "$output" | grep -qi "up to date\|up-to-date\|already up to date"; then + echo "has_change=false" >> $GITHUB_OUTPUT + echo "::notice::requirements.txt seems up to date" + else + echo "has_change=true" >> $GITHUB_OUTPUT + fi + + commit-requirements-delta: + runs-on: ubuntu-latest + needs: detect-requirements-delta + if: needs.detect-requirements-delta.outputs.has_change == 'true' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref || github.ref_name }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: 'pyproject.toml' + + - name: Install Poetry + run: pip install poetry + + - name: Generate requirements.txt + run: make requirements.txt + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Commit requirements.txt if changed + run: | + git add -f requirements.txt + if git diff --staged --quiet; then + echo "No changes to requirements.txt" + else + git commit -m "chore: auto-update requirements.txt [bot]" + git push + fi diff --git a/Makefile b/Makefile index a4ca235d..b4707b08 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,13 @@ # WARNING: Using `docker-compose` is deprecated DOCKER_COMPOSE_CMD := $(shell if command -v docker-compose > /dev/null; then echo "docker-compose"; else echo "docker compose"; fi) + +requirements.txt: poetry.lock + pip install --user poetry-plugin-export \ + && poetry export -f requirements.txt --output requirements.txt \ + && pip uninstall --yes poetry-plugin-export + + .PHONY: build build: $(DOCKER_COMPOSE_CMD) -f ./docker-compose.yml build diff --git a/TESTING.md b/TESTING.md index c1b39cd0..5a5ab2d4 100644 --- a/TESTING.md +++ b/TESTING.md @@ -1,24 +1,31 @@ # How to Test -## Local Server +- [On Free Machine](#on-free-machine) +- [On Your Machine](#on-your-machine) +- [On Our Machine](#on-our-machine) -> [!WARNING] -> Testing is manual and requires using a command prompt. +## On Free Machine + +> [!TIP] +> Create a pull request; automatically get a remote preview server. -You can [test with **PIP** or **Poetry** or **Docker** or **Make**](https://tacc.github.io/mkdocs-tacc/test/#test-locally) as a client. +## On Your Machine -## Remote Server +> [!NOTE] +> Run a server manually or programatically on your machine. -> [!WARNING] -> Your test may be overridden by others working on the same test server. +You can [test with **PIP** or **Poetry** or **Docker** or **Make**](https://tacc.github.io/mkdocs-tacc/test/#test-locally). -Deploy to our test server: +## On Our Machine + +> [!WARNING] +> Only authorized contributors may deploy to our test server. 0. Have a branch with changes ready to deploy. -1. On your branch, edit the [pre-prod workflow config](./.github/workflows/build-pprd.yml) `branches:` list. +1. On your branch, edit the [pre-prod workflow config](./.github/workflows/build-pprd.yml) `branches:` list to include your branch. 2. Commit the change to trigger the workflow. 3. Wait for [GitHub action](https://github.com/DesignSafe-CI/ds-user-guide/actions) to complete. 4. Load https://pprd.designsafe-ci.org/user-guide/. -> [!TIP] -> In the future, we will offer a dedicated test server. Task is pending [issue #61](https://github.com/DesignSafe-CI/DS-User-Guide/issues/61). +> [!CAUTION] +> Others can override your test by deploying to this server.