diff --git a/.github/workflows/main-workflow.yml b/.github/workflows/main-workflow.yml new file mode 100644 index 0000000..afb5384 --- /dev/null +++ b/.github/workflows/main-workflow.yml @@ -0,0 +1,42 @@ +name: Main Workflow + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + ci: + name: CI lint, type, test, build + uses: ./.github/workflows/reusable-ci.yml + + security: + name: Security scans + permissions: + security-events: write + actions: read + contents: read + packages: read + uses: ./.github/workflows/reusable-security.yml + + docs: + name: Deploy Documentation + permissions: + contents: write + pages: write + id-token: write + if: | # Only run docs if documentation files change + contains(github.event.head_commit.modified, 'docs/') || + contains(github.event.head_commit.modified, 'README.md') || + contains(github.event.head_commit.modified, 'CONTRIBUTING.md') || + contains(github.event.head_commit.modified, 'mkdocs.yml') + uses: ./.github/workflows/reusable-docs.yml + + cd-dev: + name: CD Dev Publishing + needs: [ci, security, docs] + if: ${{ !cancelled() }} + uses: ./.github/workflows/reusable-cd-dev.yml + secrets: inherit diff --git a/.github/workflows/cd-dev.yml b/.github/workflows/reusable-cd-dev.yml similarity index 75% rename from .github/workflows/cd-dev.yml rename to .github/workflows/reusable-cd-dev.yml index b4eb475..b62ff57 100644 --- a/.github/workflows/cd-dev.yml +++ b/.github/workflows/reusable-cd-dev.yml @@ -1,9 +1,11 @@ name: CD - Dev Publishing on: - push: - branches: [ main ] - workflow_dispatch: + workflow_call: + +env: + TEST_PYPI_UPLOAD_URL: "https://test.pypi.org/legacy/" + TEST_PYPI_INSTALL_URL: "https://test.pypi.org/simple/" jobs: publish-dev: @@ -34,7 +36,8 @@ jobs: PATCH=0 fi - DEV_VERSION="${MAJOR}.${MINOR}.${PATCH}.dev${{ github.run_number }}" + TIMESTAMP=$(date +%Y%m%d%H%M%S) + DEV_VERSION="${MAJOR}.${MINOR}.${PATCH}.dev${TIMESTAMP}" echo "Dev version: $DEV_VERSION" echo "version=$DEV_VERSION" >> $GITHUB_OUTPUT @@ -42,7 +45,7 @@ jobs: - name: Build and publish to TestPyPI uses: ./.github/actions/build-and-publish with: - pypi-upload-url: 'https://test.pypi.org/legacy/' - pypi-install-url: 'https://test.pypi.org/simple/' + pypi-upload-url: ${{ env.TEST_PYPI_UPLOAD_URL }} + pypi-install-url: ${{ env.TEST_PYPI_INSTALL_URL }} version-override: ${{ steps.version.outputs.version }} pypi-token: ${{ secrets.TEST_PYPI_API_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/reusable-ci.yml similarity index 65% rename from .github/workflows/ci.yml rename to .github/workflows/reusable-ci.yml index e32b6ef..03d08ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/reusable-ci.yml @@ -1,15 +1,11 @@ -name: Lint and Type Check +name: Lint, Checks, Automated Tests, Build Test on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -# Define reusable steps as anchors -defaults: - run: - shell: bash + workflow_call: + outputs: + overall-success: + description: "CI all checks passed" + value: ${{ jobs.aggregate-results.outputs.overall-success }} jobs: ruff-check: @@ -90,3 +86,22 @@ jobs: - name: Installation dry run run: pip install dist/*.whl + + aggregate-results: + needs: [ruff-check, ruff-format, mypy, unit-tests, build-package ] + runs-on: ubuntu-latest + outputs: + overall-success: ${{ steps.aggregate.outputs.overall-success }} + steps: + - name: Check if all jobs passed + id: aggregate + run: | + if [[ "${{ needs.ruff-check.result }}" == "success" && \ + "${{ needs.ruff-format.result }}" == "success" && \ + "${{ needs.mypy.result }}" == "success" && \ + "${{ needs.unit-tests.result }}" == "success" && \ + "${{ needs.build-package.result }}" == "success" ]]; then + echo "overall-success=true" >> $GITHUB_OUTPUT + else + echo "overall-success=false" >> $GITHUB_OUTPUT + fi diff --git a/.github/workflows/docs.yml b/.github/workflows/reusable-docs.yml similarity index 79% rename from .github/workflows/docs.yml rename to .github/workflows/reusable-docs.yml index e899230..604d4be 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -1,15 +1,7 @@ name: Deploy Documentation on: - workflow_dispatch: - push: - branches: [ main ] - paths: - - 'docs/**' - - 'mkdocs.yml' - - 'README.md' - - 'CONTRIBUTING.md' - - '.github/workflows/docs.yml' + workflow_call: permissions: contents: write diff --git a/.github/workflows/security.yml b/.github/workflows/reusable-security.yml similarity index 63% rename from .github/workflows/security.yml rename to .github/workflows/reusable-security.yml index 987641c..9a8422b 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/reusable-security.yml @@ -1,14 +1,11 @@ name: Security Scan on: - schedule: - # Run daily at 6 AM UTC - - cron: '0 6 * * *' - workflow_dispatch: # Allow manual triggers - pull_request: - branches: [ main ] - push: - branches: [ main ] + workflow_call: + outputs: + overall-success: + description: "Security all checks passed" + value: ${{ jobs.aggregate-results.outputs.overall-success }} jobs: safety-scan: @@ -75,3 +72,21 @@ jobs: uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + aggregate-results: + needs: [safety-scan, bandit-scan, codeql-scan, secret-scan] + runs-on: ubuntu-latest + outputs: + overall-success: ${{ steps.aggregate.outputs.overall-success }} + steps: + - name: Check if all jobs passed + id: aggregate + run: | + if [[ "${{ needs.safety-scan.result }}" == "success" && \ + "${{ needs.bandit-scan.result }}" == "success" && \ + "${{ needs.codeql-scan.result }}" == "success" && \ + "${{ needs.secret-scan.result }}" == "success" ]]; then + echo "overall-success=true" >> $GITHUB_OUTPUT + else + echo "overall-success=false" >> $GITHUB_OUTPUT + fi diff --git a/.github/workflows/schedule-security.yml b/.github/workflows/schedule-security.yml new file mode 100644 index 0000000..d1fdd8b --- /dev/null +++ b/.github/workflows/schedule-security.yml @@ -0,0 +1,16 @@ +name: Scheduled Security Scan + +on: + schedule: + # Run daily at 6 AM UTC + - cron: '0 6 * * *' + workflow_dispatch: # Allow manual triggers + +jobs: + security: + permissions: + security-events: write + actions: read + contents: read + packages: read + uses: ./.github/workflows/reusable-security.yml diff --git a/pyproject.toml b/pyproject.toml index 399fc8b..01f82bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,7 @@ requires = ["setuptools>=69.4.2", "wheel>=0.44.0", "setuptools-scm>=8.1.0"] build-backend = "setuptools.build_meta" + [tool.setuptools_scm] write_to = "src/tftp_router_flasher/_version.py" # Create version file version_scheme = "no-guess-dev" # Increment patch for dev