diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..40285c8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,84 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] +permissions: + contents: read + +jobs: + # ── Job 1: Lint ──────────────────────────────────────────────────── + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # TODO ②: Set up Python 3.11 using actions/setup-python + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.11 + + - name: Cache pip + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} + restore-keys: ${{ runner.os }}-pip- + + - name: Install linter + run: pip install ruff + + - name: Run lint + run: ruff check src/ + + # ── Job 2: Test ──────────────────────────────────────────────────── + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Run tests + run: pytest src/ --junitxml=test-results.xml + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results + path: test-results.xml + + # ── Job 3: Build ─────────────────────────────────────────────────── + build: + name: Build + needs: [lint, test] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build distribution + run: | + pip install build + python -m build + + - name: Upload dist artifact + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ \ No newline at end of file diff --git a/modules/02-github-actions/caching-and-matrix.md b/modules/02-github-actions/caching-and-matrix.md index b7f15ec..dc5360e 100644 --- a/modules/02-github-actions/caching-and-matrix.md +++ b/modules/02-github-actions/caching-and-matrix.md @@ -85,7 +85,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: @@ -123,7 +123,7 @@ jobs: matrix: python-version: ["3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} @@ -207,7 +207,7 @@ jobs: python-version: ["3.11", "3.12"] steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: diff --git a/modules/02-github-actions/environments-and-approvals.md b/modules/02-github-actions/environments-and-approvals.md index 2e28721..c8b8649 100644 --- a/modules/02-github-actions/environments-and-approvals.md +++ b/modules/02-github-actions/environments-and-approvals.md @@ -123,7 +123,7 @@ jobs: runs-on: ubuntu-latest environment: staging steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - run: ./scripts/deploy.sh env: DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }} @@ -133,7 +133,7 @@ jobs: needs: deploy-staging runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - run: pytest tests/smoke/ --base-url=https://staging.securithings.com deploy-production: @@ -143,7 +143,7 @@ jobs: name: production url: https://app.securithings.com steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - run: ./scripts/deploy.sh env: DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }} diff --git a/modules/02-github-actions/examples/01-basic-ci.yml b/modules/02-github-actions/examples/01-basic-ci.yml index 5dffcfb..54d6bd1 100644 --- a/modules/02-github-actions/examples/01-basic-ci.yml +++ b/modules/02-github-actions/examples/01-basic-ci.yml @@ -42,15 +42,15 @@ jobs: steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + uses: actions/setup-python@v5 with: python-version: "3.11" - name: Cache pip - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c6158d # v4.2.0 + uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} @@ -75,15 +75,15 @@ jobs: steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Cache pip - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c6158d # v4.2.0 + uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }} @@ -95,7 +95,7 @@ jobs: run: pytest src/ -v --junitxml=test-results-${{ matrix.python-version }}.xml - name: Upload test results - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@v4 if: always() with: name: test-results-py${{ matrix.python-version }} @@ -119,10 +119,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + uses: actions/setup-python@v5 with: python-version: "3.11" @@ -136,7 +136,7 @@ jobs: python -m build - name: Upload dist - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@v4 with: name: dist-${{ steps.version.outputs.tag }} path: dist/ @@ -151,7 +151,7 @@ jobs: steps: - name: Download dist - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@v4 with: name: dist-${{ needs.build.outputs.version }} path: dist/ diff --git a/modules/02-github-actions/examples/02-matrix-build-advanced.yml b/modules/02-github-actions/examples/02-matrix-build-advanced.yml index 4fd36fd..e4c0ac8 100644 --- a/modules/02-github-actions/examples/02-matrix-build-advanced.yml +++ b/modules/02-github-actions/examples/02-matrix-build-advanced.yml @@ -21,8 +21,8 @@ jobs: python-version: ["3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: python --version @@ -56,9 +56,9 @@ jobs: upload-results: false steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@v4 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} @@ -76,7 +76,7 @@ jobs: - name: Upload results if: matrix.upload-results == true - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 + uses: actions/upload-artifact@v4 with: name: results-${{ matrix.name }} path: "*.xml" @@ -89,7 +89,7 @@ jobs: outputs: services: ${{ steps.list.outputs.services }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@v4 - id: list run: | # In reality, this might scan directories or query an API @@ -106,6 +106,6 @@ jobs: service: ${{ fromJSON(needs.generate-matrix.outputs.services) }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@v4 - name: Test service run: echo "Testing service: ${{ matrix.service }}" diff --git a/modules/02-github-actions/examples/02-matrix-build.yml b/modules/02-github-actions/examples/02-matrix-build.yml index a949793..15b72aa 100644 --- a/modules/02-github-actions/examples/02-matrix-build.yml +++ b/modules/02-github-actions/examples/02-matrix-build.yml @@ -35,16 +35,16 @@ jobs: coverage: true # Only run coverage on this combination steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Cache pip (Unix) if: runner.os != 'Windows' - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c6158d # v4.2.0 + uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }} @@ -63,7 +63,7 @@ jobs: - name: Upload coverage if: matrix.coverage == true - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@v4 with: name: coverage-report path: coverage.xml diff --git a/modules/02-github-actions/examples/03-reusable-workflow-caller.yml b/modules/02-github-actions/examples/03-reusable-workflow-caller.yml index 979befa..b114d9b 100644 --- a/modules/02-github-actions/examples/03-reusable-workflow-caller.yml +++ b/modules/02-github-actions/examples/03-reusable-workflow-caller.yml @@ -28,10 +28,10 @@ jobs: version: ${{ steps.version.outputs.tag }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + uses: actions/setup-python@v5 with: python-version: "3.11" @@ -45,7 +45,7 @@ jobs: python -m build - name: Upload artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@v4 with: name: dist-${{ steps.version.outputs.tag }} path: dist/ diff --git a/modules/02-github-actions/examples/03-reusable-workflow.yml b/modules/02-github-actions/examples/03-reusable-workflow.yml index dfb8bf0..af8e968 100644 --- a/modules/02-github-actions/examples/03-reusable-workflow.yml +++ b/modules/02-github-actions/examples/03-reusable-workflow.yml @@ -45,10 +45,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@v4 - name: Download artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@v4 with: name: dist-${{ inputs.version }} path: dist/ diff --git a/modules/02-github-actions/examples/04-manual-trigger.yml b/modules/02-github-actions/examples/04-manual-trigger.yml index 457d03e..cf81b21 100644 --- a/modules/02-github-actions/examples/04-manual-trigger.yml +++ b/modules/02-github-actions/examples/04-manual-trigger.yml @@ -63,7 +63,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@v4 - name: Deploy run: | diff --git a/modules/02-github-actions/exercises/exercise.md b/modules/02-github-actions/exercises/exercise.md index 421d452..103dc32 100644 --- a/modules/02-github-actions/exercises/exercise.md +++ b/modules/02-github-actions/exercises/exercise.md @@ -37,7 +37,7 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 # TODO ②: Set up Python 3.11 using actions/setup-python @@ -61,7 +61,7 @@ jobs: # TODO ③: Add a matrix for python-version: ["3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 # TODO ④: Set up Python from the matrix variable @@ -79,7 +79,7 @@ jobs: # TODO ⑥: Make this job wait for lint AND test to succeed runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - name: Build distribution run: | diff --git a/modules/02-github-actions/jenkins-github-actions-comparison.md b/modules/02-github-actions/jenkins-github-actions-comparison.md index 66a9152..b3424ac 100644 --- a/modules/02-github-actions/jenkins-github-actions-comparison.md +++ b/modules/02-github-actions/jenkins-github-actions-comparison.md @@ -118,14 +118,14 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - run: pip install -r requirements.txt test: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - run: pytest src/ --junitxml=report.xml - uses: actions/upload-artifact@v4 if: always() @@ -139,7 +139,7 @@ jobs: runs-on: ubuntu-latest environment: production steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - run: ./scripts/deploy.sh env: TOKEN: ${{ secrets.DEPLOY_TOKEN }} diff --git a/modules/02-github-actions/passing-data.md b/modules/02-github-actions/passing-data.md index 9edd472..849a9eb 100644 --- a/modules/02-github-actions/passing-data.md +++ b/modules/02-github-actions/passing-data.md @@ -166,7 +166,7 @@ jobs: needs: prepare runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@v4 - run: python -m build - uses: actions/upload-artifact@v4 with: diff --git a/modules/02-github-actions/security-best-practices.md b/modules/02-github-actions/security-best-practices.md index 5e61174..9cd00c3 100644 --- a/modules/02-github-actions/security-best-practices.md +++ b/modules/02-github-actions/security-best-practices.md @@ -13,7 +13,7 @@ Tags (like `@v4`) can be moved to point to different code. A SHA is immutable. - uses: actions/checkout@v4 # ✅ Safe — SHA cannot be changed -- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 +- uses: actions/checkout@v4 ``` **Finding the SHA:** @@ -176,7 +176,7 @@ jobs: contents: read pull-requests: write steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@v4 - uses: actions/dependency-review-action@v4 ``` diff --git a/resources/cheatsheet.md b/resources/cheatsheet.md index c621694..f08f644 100644 --- a/resources/cheatsheet.md +++ b/resources/cheatsheet.md @@ -196,7 +196,7 @@ permissions: pull-requests: write # SHA pinning (replace tag with immutable SHA) -- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 +- uses: actions/checkout@v4 # Safe env var interpolation (not direct shell injection) - env: diff --git a/solutions/02-ci-workflow/.github/workflows/ci.yml b/solutions/02-ci-workflow/.github/workflows/ci.yml index f0acb70..5904031 100644 --- a/solutions/02-ci-workflow/.github/workflows/ci.yml +++ b/solutions/02-ci-workflow/.github/workflows/ci.yml @@ -19,13 +19,13 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@v4 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + - uses: actions/setup-python@v5 with: python-version: "3.11" - - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c6158d # v4.2.0 + - uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} @@ -45,13 +45,13 @@ jobs: python-version: ["3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@v4 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c6158d # v4.2.0 + - uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }} @@ -60,7 +60,7 @@ jobs: - run: pytest src/ -v --junitxml=test-results-${{ matrix.python-version }}.xml - - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + - uses: actions/upload-artifact@v4 if: always() with: name: test-results-py${{ matrix.python-version }} @@ -77,9 +77,9 @@ jobs: version: ${{ steps.version.outputs.tag }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@v4 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + - uses: actions/setup-python@v5 with: python-version: "3.11" @@ -89,7 +89,7 @@ jobs: - run: pip install build && python -m build - - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + - uses: actions/upload-artifact@v4 with: name: dist-${{ steps.version.outputs.tag }} path: dist/ diff --git a/src/test_app.py b/src/test_app.py index 50f4932..4f2db31 100644 --- a/src/test_app.py +++ b/src/test_app.py @@ -4,8 +4,8 @@ """ import pytest -from app import add, subtract, multiply, divide, greet, fibonacci +from app import add, divide, fibonacci, greet, multiply, subtract # ── Arithmetic ─────────────────────────────────────────────────────────────────