Browse Source

Pipeline improvements (#227)

* Use multi-stage pipeline to avoid race condition when comparing code coverage; ci script cleanups to support running locally

* Fixing bug in powershell script

* Going back to downloading artifacts instead of using API

* Fix label in pipeline

* Removing unused code coverage script (using apis)

* Adding happy output when tests pass

* Script-ifying docs build, deleting unused scripts, and adding doc build to CI pipeline

* Fixing syntax error in setup.py

* Fixing bug in make-docs.ps1
Vince Salvino 5 years ago
parent
commit
2f21b104c2
12 changed files with 366 additions and 306 deletions
  1. 122 83
      azure-pipelines.yml
  2. 48 0
      ci/compare-artifacts.ps1
  3. 32 0
      ci/make-docs.ps1
  4. 20 4
      ci/run-flake8.ps1
  5. 31 0
      ci/run-tests.ps1
  6. 0 31
      ci/run_artifacts.ps1
  7. 0 20
      ci/run_autopep8.ps1
  8. 0 20
      ci/run_black.ps1
  9. 0 19
      docs/Makefile
  10. 107 86
      docs/contributing/index.rst
  11. 0 35
      docs/make.bat
  12. 6 8
      setup.py

+ 122 - 83
azure-pipelines.yml

@@ -11,94 +11,133 @@
 #   CR-DEPLOY: for publication or deployment.
 #   [no prefix]: for unrelated CI setup/tooling.
 #
-# Use PowerShell Core for any scripts so they are re-usable across windows/mac/linux.
+# Use PowerShell Core for any utility scripts so they are re-usable across
+# Windows, macOS, and Linux.
 #
 
 
 trigger:
   - master
 
-jobs:
-- job: tests
+
+stages:
+- stage: Unit_Tests
   displayName: Unit Tests
-  pool:
-    vmImage: 'ubuntu-latest'
-  strategy:
-    matrix:
-      py3.5:
-        PYTHON_VERSION: '3.5'
-      py3.6:
-        PYTHON_VERSION: '3.6'
-      py3.7:
-        PYTHON_VERSION: '3.7'
-  
-  steps:
-  - task: UsePythonVersion@0
-    displayName: 'Use Python version'
-    inputs:
-      versionSpec: '$(PYTHON_VERSION)'
-      architecture: 'x64'
-
-  - script: |
-      python -m pip install -e ./[ci_tests]
-    displayName: 'CR-QC: Install coderedcms from local repo'
-
-  - script: |
-      coderedcms start testproject --name="Test Project" --domain="www.example.com"
-    displayName: 'CR-QC: Create starter project from template'
-
-  - script: |
-      pytest coderedcms/ --ds=coderedcms.tests.settings --junitxml=junit/test-results.xml --cov=coderedcms --cov-report=xml --cov-report=html
-    displayName: 'CR-QC: Run unit tests'
-
-  - task: PublishTestResults@2
-    displayName: 'Publish unit test report'
-    condition: succeededOrFailed()
-    inputs:
-      testResultsFiles: '**/test-*.xml'
-      testRunTitle: 'Publish test results for Python $(python.version)'
-
-  - task: PublishCodeCoverageResults@1
-    displayName: 'Publish code coverage report'
-    condition: succeededOrFailed()
-    inputs:
-      codeCoverageTool: Cobertura
-      summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage.xml'
-
-  - task: DownloadPipelineArtifact@2
-    displayName: 'Download code coverage from latest build'
-    inputs:
-      source: 'specific'
-      path: '$(Agent.WorkFolder)/artifacts'
-      project: 'cc52b8d8-3ae5-466e-b771-56f3b4749f1f'
-      pipeline: 1
-      runVersion: 'latestFromBranch'
-      runBranch: 'refs/heads/master'
-
-  - pwsh: |
-      & ci/run_artifacts.ps1
-    displayName: 'Compare code coverage to master'
-
-- job: style
+
+  jobs:
+  - job: pytest
+    displayName: pytest
+    pool:
+      vmImage: 'ubuntu-latest'
+    strategy:
+      matrix:
+        py3.5:
+          PYTHON_VERSION: '3.5'
+        py3.6:
+          PYTHON_VERSION: '3.6'
+        py3.7:
+          PYTHON_VERSION: '3.7'
+
+    steps:
+    - task: UsePythonVersion@0
+      displayName: 'Use Python version'
+      inputs:
+        versionSpec: '$(PYTHON_VERSION)'
+        architecture: 'x64'
+
+    - script: python -m pip install -e ./[ci]
+      displayName: 'CR-QC: Install coderedcms from local repo'
+
+    - script: coderedcms start testproject
+      displayName: 'CR-QC: Create starter project from template'
+
+    - pwsh: ./ci/run-tests.ps1
+      displayName: 'CR-QC: Run unit tests'
+
+    - task: PublishTestResults@2
+      displayName: 'Publish unit test report'
+      condition: succeededOrFailed()
+      inputs:
+        testResultsFiles: '**/test-*.xml'
+        testRunTitle: 'Publish test results for Python $(python.version)'
+
+    - task: PublishCodeCoverageResults@1
+      displayName: 'Publish code coverage report'
+      condition: succeededOrFailed()
+      inputs:
+        codeCoverageTool: Cobertura
+        summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage.xml'
+
+
+- stage: Static_Analysis
   displayName: Static Analysis
-  pool:
-    vmImage: 'ubuntu-latest'
-
-  steps:
-  - task: UsePythonVersion@0
-    displayName: 'Use Python version'
-    inputs:
-      versionSpec: '3.7'
-      architecture: 'x64'
-
-  - script: |
-      python -m pip install -e ./[ci_style]
-    displayName: 'CR-QC: Install coderedcms from local repo'
-
-  - script: |
-      coderedcms start testproject
-    displayName: 'CR-QC: Generate a test project'
-
-  - pwsh: |
-      & ci/run_flake8.ps1
-    displayName: 'CR-QC: Static analysis (flake8)'
+  dependsOn: Unit_Tests
+  condition: succeeded('Unit_Tests')
+  jobs:
+  - job: flake8
+    displayName: flake8
+    pool:
+      vmImage: 'ubuntu-latest'
+
+    steps:
+    - task: UsePythonVersion@0
+      displayName: 'Use Python version'
+      inputs:
+        versionSpec: '3.7'
+        architecture: 'x64'
+
+    - script: python -m pip install -e ./[ci]
+      displayName: 'CR-QC: Install coderedcms from local repo'
+
+    - script: coderedcms start testproject
+      displayName: 'CR-QC: Generate a test project'
+
+    - pwsh: ./ci/run-flake8.ps1
+      displayName: 'CR-QC: Static analysis (flake8)'
+
+  - job: codecov
+    displayName: Code Coverage
+    pool:
+      vmImage: 'ubuntu-latest'
+
+    steps:
+    - task: DownloadPipelineArtifact@2
+      displayName: 'Download code coverage from current build'
+      inputs:
+        source: 'current'
+        path: '$(Agent.WorkFolder)/current-artifacts'
+        project: '$(System.TeamProjectId)'
+        pipeline: '$(System.DefinitionId)'
+
+    - task: DownloadPipelineArtifact@2
+      displayName: 'Download code coverage from latest master build'
+      inputs:
+        source: 'specific'
+        path: '$(Agent.WorkFolder)/previous-artifacts'
+        project: '$(System.TeamProjectId)'
+        pipeline: '$(System.DefinitionId)'
+        runVersion: 'latestFromBranch'
+        runBranch: 'refs/heads/master'
+
+    - pwsh: ./ci/compare-artifacts.ps1 -wd $Env:WorkDir
+      displayName: 'CR-QC: Compare code coverage'
+      env:
+        WorkDir: $(Agent.WorkFolder)
+
+  - job: docs
+    displayName: Documentation
+    pool:
+      vmImage: 'ubuntu-latest'
+
+    steps:
+    - task: UsePythonVersion@0
+      displayName: 'Use Python version'
+      inputs:
+        versionSpec: '3.7'
+        architecture: 'x64'
+
+    - script: python -m pip install -e ./[ci]
+      displayName: 'CR-QC: Install coderedcms from local repo'
+
+    - pwsh: ./ci/make-docs.ps1
+      displayName: 'CR-QC: Build documentation'

+ 48 - 0
ci/compare-artifacts.ps1

@@ -0,0 +1,48 @@
+#!/usr/bin/env pwsh
+
+<#
+.SYNOPSIS
+Used by Azure Pipelines to compare code coverage reports between master and current branch.
+
+.PARAMETER wd
+The working directory in which to find downloaded artifacts.
+#>
+
+param([string]$wd)
+
+if (Test-Path -Path "$wd/current-artifacts/Code Coverage Report_*/summary*/coverage.xml") {
+    [xml]$BranchXML = Get-Content "$wd/current-artifacts/Code Coverage Report_*/summary*/coverage.xml"
+} else {
+    Write-Host "No code coverage from this build. Is pytest configured to output code coverage? Exiting pipeline." -ForegroundColor Red
+    exit 1
+}
+
+if (Test-Path -Path "$wd/previous-artifacts/Code Coverage Report_*/summary*/coverage.xml") {
+    [xml]$MasterXML = Get-Content "$wd/previous-artifacts/Code Coverage Report_*/summary*/coverage.xml"
+} else {
+    Write-Host "No code coverage from previous build. Exiting pipeline." -ForegroundColor Red
+    exit 2
+}
+
+$masterlinerate = [math]::Round([decimal]$MasterXML.coverage.'line-rate' * 100, 2)
+$branchlinerate = [math]::Round([decimal]$BranchXML.coverage.'line-rate' * 100, 2)
+
+Write-Output "Master line coverage rate:  $masterlinerate%"
+Write-Output "Branch line coverage rate:  $branchlinerate%"
+
+if ($masterlinerate -eq 0) {
+    $change = "Infinite"
+} else {
+    $change = [math]::Abs($branchlinerate - $masterlinerate)
+}
+
+if ($branchlinerate -gt $masterlinerate) {
+    Write-Host "Coverage increased by $change% 😀" -ForegroundColor Green
+    exit 0
+} elseif ($branchlinerate -eq $masterlinerate) {
+    Write-Host "Coverage has not changed." -ForegroundColor Green
+    exit 0
+} else {
+    Write-Host "Coverage decreased by $change% 😭" -ForegroundColor Red
+    exit 4
+}

+ 32 - 0
ci/make-docs.ps1

@@ -0,0 +1,32 @@
+#!/usr/bin/env pwsh
+
+<#
+.SYNOPSIS
+Builds the documentation as HTML.
+#>
+
+# Get path.
+$scriptDir = Split-Path $PSCommandPath -Parent
+$projectDir = (Get-Item $scriptDir).Parent
+$docsDir = Join-Path -Path $projectDir -ChildPath "docs"
+$docsBuildDir = Join-Path -Path $docsDir -ChildPath "_build"
+
+$ExitCode = 0
+
+# Clean previously built docs.
+sphinx-build -M clean $docsDir $docsBuildDir
+
+# Make docs, treat warnigs as errors.
+sphinx-build -M html $docsDir $docsBuildDir -W
+$ExitCode = $LastExitCode
+
+# Write output for humans.
+if ($ExitCode -eq 0) {
+    Write-Host "Docs have been built! 📜" -ForegroundColor Green
+}
+else {
+    Write-Host "There were warnings or errors building docs. 😭" -ForegroundColor Red
+}
+
+# Exit with sphinx's code.
+exit $ExitCode

+ 20 - 4
ci/run_flake8.ps1 → ci/run-flake8.ps1

@@ -1,9 +1,23 @@
 #!/usr/bin/env pwsh
 
+<#
+.SYNOPSIS
+Runs flake8 to analyze Python source code for errors and best practices.
+#>
+
+# Get path.
+$scriptDir = Split-Path $PSCommandPath -Parent
+$projectDir = (Get-Item $scriptDir).Parent
+
+# Set working directory to root of project.
+Push-Location $projectDir
+
+# Get the diff for the current branch.
 $ExitCode = 0
 $GitDiff = git diff origin/master
+
 # If there is no diff between master, then flake8 everything.
-if ( $GitDiff -eq $null ) {
+if ( $null -eq $GitDiff ) {
     flake8 .
     if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
 }
@@ -13,18 +27,20 @@ else {
     if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
     # If the project_template changed, then flake8 the testproject too.
     $GitDiffTempl = Write-Output $GitDiff | Select-String -Pattern "^diff .*/project_template/.*"
-    if ( $GitDiffTempl -ne $null ) {
+    if ( $null -ne $GitDiffTempl ) {
         flake8 testproject
         if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
     }
 }
 
-# Write friendly output
+# Write output for humans.
 if ($ExitCode -eq 0) {
     Write-Host -ForegroundColor Green "[✔] Flake8 passed with no errors"
 }
 else {
-    Write-Host -ForegroundColor Red "[] Flake8 exited with errors. Please resolve issues above."
+    Write-Host -ForegroundColor Red "[X] Flake8 exited with errors. Please resolve issues above."
 }
 
+# Unset working directory and exit with flake8's exit code.
+Pop-Location
 exit $ExitCode

+ 31 - 0
ci/run-tests.ps1

@@ -0,0 +1,31 @@
+#!/usr/bin/env pwsh
+
+<#
+.SYNOPSIS
+Runs unit tests. Outputs test results and code coverage report.
+#>
+
+# Get path.
+$scriptDir = Split-Path $PSCommandPath -Parent
+$projectDir = (Get-Item $scriptDir).Parent
+
+# Set working directory to root of project.
+Push-Location $projectDir
+
+$ExitCode = 0
+
+# Run unit tests.
+pytest coderedcms/ --ds=coderedcms.tests.settings --junitxml=junit/test-results.xml --cov=coderedcms --cov-report=xml --cov-report=html
+$ExitCode = $LastExitCode
+
+# Print code coverage if succeeded.
+if ($ExitCode -eq 0) {
+    [xml]$BranchXML = Get-Content coverage.xml
+    $LineRate = [math]::Round([decimal]$BranchXML.coverage.'line-rate' * 100, 2)
+    Write-Output "All unit tests passed! 🎉"
+    Write-Output "Code coverage: $LineRate%"
+}
+
+# Unset working directory and exit with pytest's code.
+Pop-Location
+exit $ExitCode

+ 0 - 31
ci/run_artifacts.ps1

@@ -1,31 +0,0 @@
-if (Test-Path -Path "/home/vsts/work/artifacts/Code Coverage Report_*/summary*/coverage.xml") {
-    [xml]$MasterXML = Get-Content "/home/vsts/work/artifacts/Code Coverage Report_*/summary*/coverage.xml"
-} else {
-    Write-Host "No code coverage from previous build. Exiting pipeline." -ForegroundColor Red
-    exit 1
-}
-
-[xml]$BranchXML = Get-Content .\coverage.xml
-
-$masterlinerate = [math]::Abs([math]::Round([decimal]$MasterXML.coverage.'line-rate' * 100, 2))
-$branchlinerate = [math]::Abs([math]::Round([decimal]$BranchXML.coverage.'line-rate' * 100, 2))
-
-Write-Output "Old line coverage rate: $masterlinerate%"
-Write-Output "New line coverage rate: $branchlinerate%"
-
-if ($masterlinerate -eq 0) {
-    $change = "Infinite"
-} else {
-    $change = [math]::Abs([math]::Round((($branchlinerate - $masterlinerate) / $masterlinerate) * 100, 2))
-}
-
-if ($branchlinerate -gt $masterlinerate) {
-    Write-Host "Code coverage has increased by $change%. Build passed." -ForegroundColor Green
-    exit 0
-} elseif ($branchlinerate -eq $masterlinerate) {
-    Write-Host "Code coverage has not changed. Build passed." -ForegroundColor Green
-    exit 0
-} else {
-    Write-Host "Code coverage as decreased by $change%. Code coverage must be greater than or equal to the previous build to pass." -ForegroundColor Red
-    exit 2
-}

+ 0 - 20
ci/run_autopep8.ps1

@@ -1,20 +0,0 @@
-$ExitCode = 0
-$GitDiff = git diff --name-only origin/master
-$GitDiffPep = Write-Output $GitDiff | Select-String -Pattern ".*\.py" | Select-String -NotMatch ".*/project_template/.*"
-# If there is no diff between master, then run everything.
-if ( $GitDiffPep -eq $null ) {
-    autopep8 -r --diff coderedcms/
-    if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
-}
-# Else run just the diff.
-else {
-    autopep8 -r --diff $GitDiffPep
-    if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
-    # If the project_template changed, then run the testproject too.
-    $GitDiffTempl = Write-Output $GitDiff | Select-String -Pattern ".*/project_template/.*"
-    if ( $GitDiffTempl -ne $null ) {
-        #autopep8 -r --diff testproject/
-        if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
-    }
-}
-exit $ExitCode

+ 0 - 20
ci/run_black.ps1

@@ -1,20 +0,0 @@
-$ExitCode = 0
-$GitDiff = git diff --name-only origin/master
-$GitDiffBlack = Write-Output $GitDiff | Select-String -Pattern ".*\.py" | Select-String -NotMatch ".*/project_template/.*"
-# If there is no diff between master, then black everything.
-if ( $GitDiffBlack -eq $null ) {
-    black --check .
-    if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
-}
-# Else black just the diff.
-else {
-    black --check $GitDiffBlack
-    if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
-    # If the project_template changed, then black the testproject too.
-    $GitDiffTempl = Write-Output $GitDiff | Select-String -Pattern ".*/project_template/.*"
-    if ( $GitDiffTempl -ne $null ) {
-        black --check testproject/
-        if ($LastExitCode -ne 0) { $ExitCode = $LastExitCode }
-    }
-}
-exit $ExitCode

+ 0 - 19
docs/Makefile

@@ -1,19 +0,0 @@
-# Minimal makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-SOURCEDIR     = .
-BUILDDIR      = _build
-
-# Put it first so that "make" without argument is like "make help".
-help:
-	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-
-.PHONY: help Makefile
-
-# Catch-all target: route all unknown targets to Sphinx using the new
-# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
-%: Makefile
-	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

+ 107 - 86
docs/contributing/index.rst

@@ -8,33 +8,56 @@ Developing CodeRed CMS
 To create a test project locally:
 
 #. Clone the code from https://github.com/coderedcorp/coderedcms.
-#. Run ``pip install -e ./[dev]`` from the root coderedcms directory. The -e flag makes the install editable,
-   which is relevant when running ``makemigrations`` in test project to actually generate the migration
-   files in the coderedcms pip package. The ``[dev]`` installs extras such as sphinx for generating docs.
+#. Run ``pip install -e ./[dev]`` from the root coderedcms directory.
+   The -e flag makes the install editable, which is relevant when running
+   ``makemigrations`` in test project to actually generate the migration files
+   in the coderedcms pip package. The ``[dev]`` installs extras such as sphinx
+   for generating docs.
 #. Follow the steps in :doc:`/getting_started/install`. Use ``testproject`` for
    your project name to ensure it is ignored by git.
-#. When making model or block changes within coderedcms, run ``makemigrations coderedcms`` in the
-   test project to generate the relevant migration files for the pip package. ALWAYS follow steps
-   4 and 5 in :doc:`/getting_started/install` with a fresh database before making migrations.
-#. When model or block changes affect the local test project (i.e. the "website" app), run
-   ``makemigrations website`` in the test project to generate the relevant migration files locally.
-   Apply and test the migrations. When satisfied, re-generate the ``0001_initial.py`` migration in
+#. When making model or block changes within coderedcms, run
+   ``makemigrations coderedcms`` in the test project to generate the relevant
+   migration files for the pip package. ALWAYS follow steps 4 and 5 in
+   :doc:`/getting_started/install` with a fresh database before making migrations.
+#. When model or block changes affect the local test project (i.e. the "website"
+   app), run ``makemigrations website`` in the test project to generate the
+   relevant migration files locally. Apply and test the migrations. When
+   satisfied, re-generate the ``0001_initial.py`` migration in
    ``project_template/website/migrations/`` as so:
 
        #. Create a new test project using ``coderedcms start testproject``.
-       #. Before running migrations, DELETE all migrations in ``testproject/website/migrations/``.
-       #. Run ``python manage.py makemigrations website``. This should generate an ``0001_initial.py``
-          migration.
-       #. Replace ``project_template/website/migrations/0001_initial.py`` with your newly generated migration.
-
-When making changes that are potentially destructive or backwards incompatible, increment the minor
-version number until coderedcms reaches a stable 1.0 release. Each production project that uses
-coderedcms should specify the appropriate version in its requirements.txt to prevent breakage.
+       #. Before running migrations, DELETE all migrations in
+          ``testproject/website/migrations/``.
+       #. Run ``python manage.py makemigrations website``. This should generate
+          an ``0001_initial.py`` migration.
+       #. Replace ``project_template/website/migrations/0001_initial.py`` with
+          your newly generated migration.
+
+When making changes that are potentially destructive or backwards incompatible,
+increment the minor version number until coderedcms reaches a stable 1.0 release.
+Each production project that uses coderedcms should specify the appropriate
+version in its requirements.txt to prevent breakage.
 
 .. note::
-    When testing existing projects with coderedcms installed from the master or development branches,
-    be sure to use a disposable database, as it is likely that the migrations in master will
-    not be the same migrations that get released.
+    When testing existing projects with coderedcms installed from the master or
+    development branches, be sure to use a disposable database, as it is likely
+    that the migrations in master will not be the same migrations that get
+    released.
+
+
+A Note on Cross-Platform Support
+--------------------------------
+
+CodeRed CMS works equally well on Windows, macOS, and Linux. When adding new features
+or new dependencies, ensure that these utilize proper cross-platform utilities in Python.
+
+To ease local development of CodeRed CMS, we have many automation scripts using
+`PowerShell Core <https://github.com/powershell/powershell>`_ because it provides high quality
+commercial support for Windows, macOS, and Linux. Throughout this contributing guide,
+you will encounter various PowerShell scripts which always provide the easiest and most
+definitive way of working on CodeRed CMS.
+
+Our goal is that users of any platform can develop or host a CodeRed CMS website easily.
 
 
 CSS Development
@@ -92,99 +115,97 @@ license header comment states copyright, ownership, license, and also provides c
 Testing CodeRed CMS
 -------------------
 
-To run the built in tests for CodeRed CMS using Django, run the following:
+To run the unit tests, run the following command. This will output a unit test
+report and code coverage report:
 
 .. code-block:: console
 
-    $ python testproject/manage.py test coderedcms --settings=coderedcms.tests.settings
+    $ pytest coderedcms/ --ds=coderedcms.tests.settings --junitxml=junit/test-results.xml --cov=coderedcms --cov-report=xml --cov-report=html
 
-Or, to use ``pytest`` and output a unit test report and code coverage report (this how CI runs the tests):
+Or more conveniently, run the PowerShell script, which will also print out the
+code coverage percentage in the console:
 
 .. code-block:: console
 
-    $ pytest coderedcms/ --ds=coderedcms.tests.settings --junitxml=junit/test-results.xml --cov=coderedcms --cov-report=xml --cov-report=html
+    $ ./ci/run-tests.ps1
 
-Detailed test coverage reports are now available by opening ``htmlcov/index.html`` in your browser (which is ignored by version control)
+Detailed test coverage reports are now available by opening ``htmlcov/index.html``
+in your browser (which is ignored by version control)
 
 
 Adding New Tests
 ----------------
 
-Test coverage at the moment is fairly minimal and it is highly recommended that new features and models include proper unit tests.
-Any testing infrastructure (i.e. implementations of abstract models and migrations) needed should be added to the ``tests`` app in your
-local copy of CodeRed CMS.  The tests themselves should be in their relevant section in CodeRed CMS (i.e. tests for
-models in ``coderedcms.models.page_models`` should be located in ``coderedcms.models.tests.test_page_models``).
+Test coverage at the moment is fairly minimal and it is highly recommended that
+new features and models include proper unit tests. Any testing infrastructure
+(i.e. implementations of abstract models and migrations) needed should be added
+to the ``tests`` app in your local copy of CodeRed CMS. The tests themselves
+should be in their relevant section in CodeRed CMS (i.e. tests for models in
+``coderedcms.models.page_models`` should be located in
+``coderedcms.models.tests.test_page_models``).
 
-For example, here is how you would add tests for a new abstract page type, ``CoderedCustomPage`` that would live in ``coderedcms/models/page_models.py``:
+For example, here is how you would add tests for a new abstract page type,
+``CoderedCustomPage`` that would live in ``coderedcms/models/page_models.py``:
 
-1. Navigate to ``coderedcms/tests/testapp/models.py``
-2. Add the following import: ``from coderedcms.models.page_models import CoderedCustomPage``
-3. Implement a concrete version of ``CoderedCustomPage``, i.e. ``CustomPage(CoderedCustomPage)``.
-4. Run ``python manage.py makemigrations`` to make new testing migrations.
-5. Navigate to ``coderedcms/models/tests/test_page_models.py``
-6. Add the following import: ``from coderedcms.models import CoderedCustomPage``
-7. Add the following import: ``from coderedcms.tests.testapp.models import CustomPage``
-8. Add the following to the bottom of the file:
+#. Navigate to ``coderedcms/tests/testapp/models.py``
+#. Add the following import: ``from coderedcms.models.page_models import CoderedCustomPage``
+#. Implement a concrete version of ``CoderedCustomPage``, i.e. ``CustomPage(CoderedCustomPage)``.
+#. Run ``python manage.py makemigrations`` to make new testing migrations.
+#. Navigate to ``coderedcms/models/tests/test_page_models.py``
+#. Add the following import: ``from coderedcms.models import CoderedCustomPage``
+#. Add the following import: ``from coderedcms.tests.testapp.models import CustomPage``
+#. Add the following to the bottom of the file:
 
-.. code-block:: python
+   .. code-block:: python
 
-    class CoderedCustomPageTestCase(AbstractPageTestCase, WagtailPageTests):
-        model = CoderedCustomPage
+       class CoderedCustomPageTestCase(AbstractPageTestCase, WagtailPageTests):
+           model = CoderedCustomPage
 
-9. Add the following to the bottom of the file:
+#. Add the following to the bottom of the file:
 
-.. code-block:: python
+   .. code-block:: python
 
-    class CustomPageTestCase(ConcreteBasicPageTestCase, WagtailPageTests):
-        model = CustomPage
+       class CustomPageTestCase(ConcreteBasicPageTestCase, WagtailPageTests):
+           model = CustomPage
 
-10. Write any specific test cases that ``CoderedCustomPage`` and ``CustomPage`` may require.
+#. Write any specific test cases that ``CoderedCustomPage`` and ``CustomPage``
+   may require.
 
 
 Static Analysis
 ---------------
 
-Flake8 is used to check for syntax and style errors. To analyze the entire codebase, run:
+Flake8 is used to check for syntax and style errors. To analyze the entire
+codebase, run:
 
 .. code-block:: console
 
     $ flake8 .
 
-Alternatively, our continuous integration only analyzes the diff between your changes
-and master. To analyze just the diff of your current changes, run the
+Alternatively, our continuous integration only analyzes the diff between your
+changes and master. To analyze just the diff of your current changes, run the
 `PowerShell Core <https://github.com/powershell/powershell>`_ script:
 
 .. code-block:: console
 
-    $ ./ci/run_flake8.ps1
-
-
-
-A Note on Cross-Platform Support
---------------------------------
-
-CodeRed CMS works equally well on Windows, MacOS, and Linux. When adding new features
-or new dependencies, ensure that these utilize proper cross-platform utilities in Python.
-
-For shell or automation scripts, we default to
-`PowerShell Core <https://github.com/powershell/powershell>`_ because it provides high quality
-commercial support for Windows, MacOS, and Linux.
-
-Our goal is that users of any platform can develop or host a CodeRed CMS website easily.
+    $ ./ci/run-flake8.ps1
 
 
 Contributor Guidelines
 ----------------------
 
-We are happy to accept pull requests from the community if it aligns with our vision for coderedcms.
-When creating a pull request, please make sure you include the following:
+We are happy to accept pull requests from the community if it aligns with our
+vision for coderedcms. When creating a pull request, please make sure you
+include the following:
 
 * A description in the pull request of what this change does and how it works.
-* Reference to an issue if the change is related to one of the issues on our GitHub page.
+* Reference to an issue if the change is related to one of the issues on our
+  GitHub page.
 * Documentation updates in the ``docs/`` directory describing your change.
 
-Following submission of your pull request, a CodeRed member will review and test your change.
-**All changes, even by CodeRed members, must go through a pull request process to ensure quality.**
+Following submission of your pull request, a CodeRed member will review and test
+your change. **All changes, even by CodeRed members, must go through a pull
+request process to ensure quality.**
 
 
 Building Python Packages
@@ -200,17 +221,19 @@ To build a publicly consumable pip package, run:
 Building Documentation
 ----------------------
 
-For every code or feature change, be sure to update the docs in the repository. To build and publish
-the documentation run:
+For every code or feature change, be sure to update the docs in the repository.
+To build the documentation run the PowerShell script, which will also check for
+errors in the documentation:
 
 .. code-block:: console
 
-    $ cd docs/
-    $ make clean
-    $ make html
+    $ ./ci/make-docs.ps1
 
-.. note::
-    Windows users should run ``make.bat`` instead of ``make`` above.
+Or manually using sphinx:
+
+.. code-block:: console
+
+    $ sphinx-build -M html docs/ docs/_build/ -W
 
 Output will be in ``docs/_build/html/`` directory.
 
@@ -236,23 +259,21 @@ Finally build and update docs:
 
 .. code-block:: console
 
-    $ cd docs/
-    $ make clean
-    $ make html
-
-.. note::
-    Windows users should run ``make.bat`` instead of ``make`` above.
+    $ ./ci/make-docs.ps1
 
 If updating docs for an existing minor version release:
 
-#. Copy the contents of ``docs/_build/html/`` to the CodeRed docs server under the existing version directory.
+#. Copy the contents of ``docs/_build/html/`` to the CodeRed docs server under
+   the existing version directory.
 
 If this is a new major or minor version release:
 
 #. Create a new ``major.minor`` directory on the CodeRed docs server.
 #. Update the ``stable`` symbolic link to point to the new version directory.
 #. Add the new version to the ``versions.txt`` file on the docs server.
-#. Copy the contents of ``docs/_build/html/`` to the CodeRed docs server under the new version directory.
+#. Copy the contents of ``docs/_build/html/`` to the CodeRed docs server under
+   the new version directory.
 
-Note that we do not release separate documentation versions for maintenance releases. Update the existing minor
-version docs with release notes and other changes.
+Note that we do not release separate documentation versions for maintenance
+releases. Update the existing minor version docs with release notes and other
+changes.

+ 0 - 35
docs/make.bat

@@ -1,35 +0,0 @@
-@ECHO OFF
-
-pushd %~dp0
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
-	set SPHINXBUILD=sphinx-build
-)
-set SOURCEDIR=.
-set BUILDDIR=_build
-
-if "%1" == "" goto help
-
-%SPHINXBUILD% >NUL 2>NUL
-if errorlevel 9009 (
-	echo.
-	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
-	echo.installed, then set the SPHINXBUILD environment variable to point
-	echo.to the full path of the 'sphinx-build' executable. Alternatively you
-	echo.may add the Sphinx directory to PATH.
-	echo.
-	echo.If you don't have Sphinx installed, grab it from
-	echo.http://sphinx-doc.org/
-	exit /b 1
-)
-
-%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
-goto end
-
-:help
-%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
-
-:end
-popd

+ 6 - 8
setup.py

@@ -55,9 +55,13 @@ setup(
         'wagtail-import-export>=0.1,<0.2'
     ],
     extras_require={
+        "ci": [
+            "flake8",
+            "pytest-cov",
+            "pytest-django",
+            "sphinx"
+        ],
         "dev": [
-            # "autopep8",
-            # "black",
             "flake8",
             "libsass",
             "pytest-cov",
@@ -65,12 +69,6 @@ setup(
             "sphinx",
             "twine",
             "wheel",
-        ],  # noqa
-        "ci_tests": ["pytest-cov", "pytest-django"],
-        "ci_style": [
-            # "autopep8",
-            # "black",
-            "flake8"
         ],
     },
     entry_points="""