diff --git a/.github/workflows/changelog.yaml b/.github/workflows/changelog.yaml index 90e7ef2e..5e18814f 100644 --- a/.github/workflows/changelog.yaml +++ b/.github/workflows/changelog.yaml @@ -2,11 +2,20 @@ name: Changelog on: push: - branches: [ develop ] + branches: + - develop + create: + branches: + - develop jobs: generate: - if: contains(toJson(github.event.commits), 'Update changelog') == false + if: > + ! contains(github.event.head_commit.message, '[ci skip]') && + ! ( + startsWith(github.event.head_commit.message, 'Increment version to v') && + startsWith(github.ref, 'refs/heads/') + ) runs-on: ubuntu-latest steps: @@ -14,31 +23,70 @@ jobs: with: token: ${{ secrets.JRNL_BOT_TOKEN }} - - name: Check branch for new commits + - name: Check branch for new commits, and env vars run: | - git fetch origin - git fetch --tags origin + echo "::group::git fetch origin --tags --force" + git fetch origin --tags --force + echo "::endgroup::" + + TAG_REGEX='include-all' + echo "::debug::GITHUB_REF: $GITHUB_REF" BRANCH="${GITHUB_REF##*/}" - if [[ $(git rev-parse "origin/$BRANCH") != $GITHUB_SHA ]]; then - echo "BRANCH: $BRANCH" - echo "GITHUB_SHA: $GITHUB_SHA" - echo "$BRANCH has been updated since build started. Aborting changelog." + + if [[ $GITHUB_REF =~ ^refs/tags/ ]]; then + # This is a tag build (i.e. a release) + echo '::debug::Release build' + if [[ ! $BRANCH =~ ^v[0-9]+(\.[0-9]+){1,2}(-(alpha|beta)(\.[0-9]+)?)?$ ]]; then + echo "::error::Invalid tag format: ${BRANCH}" + exit 1 + fi + + RELEASE=1 + BRANCH=develop + git checkout $BRANCH + + # if actual release (not pre), then changelog should exclude prereleases on update + prerelease_regex='(alpha|beta)' + if [[ ! ${GITHUB_REF##*/} =~ $prerelease_regex ]]; then + echo '::debug::Actual release (not a prerelease)' + TAG_REGEX="$prerelease_regex" + echo "FULL_RELEASE=true" >> $GITHUB_ENV + fi + fi + echo "::debug::TAG_REGEX: $TAG_REGEX" + + if [[ "$(git rev-parse "origin/$BRANCH")" != $GITHUB_SHA ]]; then + # Normal build on a branch (no tag) + echo "::debug::BRANCH: $BRANCH" + echo "::debug::GITHUB_SHA: $GITHUB_SHA" + echo "::error::$BRANCH has been updated since build started. Aborting changelog." exit 1 fi - echo "BRANCH=$BRANCH" >> $GITHUB_ENV - - name: Prep environment variables - run: | - echo "BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV + SINCE_TAG=$(git tag --sort=-creatordate | grep -Ev "$TAG_REGEX" | awk "NR==$(( 1 + ${RELEASE:-0} ))") + + echo "::debug::BRANCH: $BRANCH" + echo "::debug::TAG_REGEX: $TAG_REGEX" + echo "::debug::FILENAME: CHANGELOG.md" + echo "::debug::SINCE_TAG: $SINCE_TAG" + + echo "BRANCH=$BRANCH" >> $GITHUB_ENV + echo "TAG_REGEX=$TAG_REGEX" >> $GITHUB_ENV echo "FILENAME=CHANGELOG.md" >> $GITHUB_ENV - echo "gittag=$(git tag --sort=-creatordate | grep -Ev '(alpha|beta|rc)' | awk 'NR==1')" >> $GITHUB_ENV + echo "SINCE_TAG=$SINCE_TAG" >> $GITHUB_ENV - name: Prep changelog file (clear out old lines) run: | # delete the top of the changelog up to the correct tag - tagline=$(grep -n "^## \[\?$gittag\]\?" "$FILENAME" | awk '{print $1}' FS=':' | head -1) + tagline=$(grep -n "^## \[\?${SINCE_TAG}\]\?" "$FILENAME" | awk '{print $1}' FS=':' | head -1) echo "tagline: ${tagline}" - [[ ! -z $tagline ]] && sed -i "1,$(expr $tagline - 1)d" "$FILENAME" + + if [[ -z $tagline ]]; then + echo "::error::Something is wrong. ${SINCE_TAG} isn't in the changelog." + exit 1 + fi + + sed -i "1,$(expr $tagline - 1)d" "$FILENAME" # delete generated line (or it will be added multiple times) sed -i '/This Changelog was automatically generated by/d' "$FILENAME" # delete trailing empty lines @@ -59,10 +107,11 @@ jobs: compareLink: true includeLabels: bug,enhancement,documentation,build,deprecated excludeLabels: stale,wontfix - excludeTagsRegex: '(alpha|beta|rc)' - sinceTag: ${{ env.gittag }} + excludeTagsRegex: ${{ env.TAG_REGEX }} + sinceTag: ${{ env.SINCE_TAG }} maxIssues: 150 releaseUrl: https://pypi.org/project/jrnl/%s/ + releaseBranch: develop verbose: false - name: Small fixes @@ -70,19 +119,28 @@ jobs: # Change unreleased link to correct url sed -i 's!https://pypi.org/project/jrnl/HEAD/!https://github.com/jrnl-org/jrnl/!' "$FILENAME" - - name: Consistency check + - name: Diff and consistency check run: | + git diff if [[ $(grep -c '^# Changelog$' "$FILENAME") != 1 ]]; then - echo 'Something is wrong with the changelog.' - git diff -- "$FILENAME" - exit 1 + echo '::error::Something is wrong with the changelog.' fi + SOMETHING_CHANGED=false + git diff --exit-code || SOMETHING_CHANGED=true - name: Commit + if: env.SOMETHING_CHANGED run: | git config user.email "jrnl.bot@gmail.com" git config user.name "Jrnl Bot" git add "$FILENAME" - git commit -m "Update changelog" + git commit -m "Update changelog [ci skip]" git push origin $BRANCH + - name: Merge to Release branch + if: env.FULL_RELEASE + run: | + git checkout release + git merge --ff-only $BRANCH + git push origin release + diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 00000000..acbbf49f --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,82 @@ +name: Docs + +on: + push: + branches: [ develop, release ] + paths: + - 'docs/**' + - 'mkdocs.yml' + - 'readthedocs.yml' + pull_request_target: + branches: [ develop ] + paths: + - 'docs/**' + - 'mkdocs.yml' + - 'readthedocs.yml' + +jobs: + accessibility: + if: contains(toJson(github.event.commits), '[ci skip]') == false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - name: Setup Node.js environment + uses: actions/setup-node@main + + - name: poetry cache + uses: actions/cache@v2 + with: + path: .venv + key: ${{ runner.os }}-${{ hashFiles('poetry.lock') }}-${{ matrix.python-version }} + + - name: Install dependencies + run: | + pip install poetry + poetry config --local virtualenvs.in-project true + poetry install --no-root --remove-untracked + npm install pa11y pa11y-reporter-junit + + - name: Start docs server + run: poetry run mkdocs serve & + + - name: Accessibility testing (Pa11y) + run: poetry run .github/workflows/pa11y.sh + + - name: Upload Unit Test Results + if: always() + uses: actions/upload-artifact@v2 + with: + name: Unit Test Results (pa11y) + path: reports/pa11y/*.xml + + publish-test-results: + if: success() || failure() + name: "Publish Unit Tests Results" + needs: accessibility + runs-on: ubuntu-latest + + steps: + - name: Download Artifacts + uses: actions/download-artifact@v2 + with: + path: artifacts + + - name: Publish Unit Test Results + uses: EnricoMi/publish-unit-test-result-action@v1.4 + if: always() + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + check_name: Unit Test Results + hide_comments: all but latest + comment_on_pr: true + files: '**/*.xml' + report_individual_runs: true + deduplicate_classes_by_file_name: false + diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..5a76bcf3 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,76 @@ +name: Release +on: + workflow_dispatch: + inputs: + version: + description: 'Version (e.g. v2.5 or v2.5.1-beta)' + required: true + +jobs: + validate: + name: "Validate version string" + runs-on: ubuntu-latest + steps: + - name: Validate version + run: | + JRNL_VERSION="${{ github.event.inputs.version }}" + if [[ ! $JRNL_VERSION =~ ^v[0-9]+(\.[0-9]+){1,2}(-(alpha|beta)(\.[0-9]+)?)?$ ]]; then + echo + echo "::error::Bad version" + echo + echo "Version string should match pattern above." + echo "Here are some examples of valid version numbers:" + echo + echo " v2.5" + echo " v2.5-alpha" + echo " v2.5-beta" + echo " v2.5.1" + echo " v2.5.1-alpha" + echo " v2.5.1-beta" + exit 1 + fi + echo "::debug::version: $JRNL_VERSION" + echo "JRNL_VERSION=$JRNL_VERSION" >> $GITHUB_ENV + + release_pypi: + needs: validate + name: "Release to PyPI" + runs-on: ubuntu-latest + steps: + - name: Get version + run: | + JRNL_VERSION="${{ github.event.inputs.version }}" + echo "::debug::version: $JRNL_VERSION" + echo "JRNL_VERSION=$JRNL_VERSION" >> $GITHUB_ENV + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - uses: actions/checkout@v2 + with: + token: ${{ secrets.JRNL_BOT_TOKEN }} + + - name: Install dependencies + run: pip install poetry + + - name: Update version in files + run: | + poetry version "$JRNL_VERSION" + echo __version__ = \"$JRNL_VERSION\" > jrnl/__version__.py + + - name: Commit updated files + run: | + git config user.email "jrnl.bot@gmail.com" + git config user.name "Jrnl Bot" + git add pyproject.toml jrnl/__version__.py + git commit -m "Increment version to ${JRNL_VERSION}" + git tag -a -m "$JRNL_VERSION" "$JRNL_VERSION" + git push origin develop --tags + + - name: Deploy to PyPI + run: | + poetry config http-basic.pypi "__token__" "${POETRY_PYPI_TOKEN_PYPI}" + poetry publish --build + diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 34c07ccc..27eeb340 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -3,11 +3,25 @@ name: Testing on: push: branches: [ develop, release ] + paths: + - 'jrnl/**' + - 'features/**' + - 'tests/**' + - 'poetry.lock' + - 'pyproject.toml' pull_request_target: branches: [ develop ] + paths: + - 'jrnl/**' + - 'features/**' + - 'tests/**' + - 'poetry.lock' + - 'pyproject.toml' jobs: test: + if: > + ! contains(github.event.head_commit.message, '[ci skip]') runs-on: ${{ matrix.os }} strategy: matrix: @@ -35,79 +49,37 @@ jobs: poetry install --remove-untracked - name: Code formatting (Black) - if: always() + if: success() || failure() run: | poetry run black --version poetry run black --check --diff . - name: Code Style (PyFlakes) - if: always() + if: success() || failure() run: | poetry run pyflakes --version poetry run pyflakes jrnl features tests - name: Test with pytest - if: always() + if: success() || failure() run: poetry run pytest --junitxml=reports/pytest/results.xml - name: Test with behave - if: always() + if: success() || failure() run: poetry run behave --no-skipped --format progress2 --junit --junit-directory reports/behave - name: Upload Unit Test Results - if: always() + if: success() || failure() uses: actions/upload-artifact@v2 with: name: Unit Test Results path: reports/**/*.xml - - accessibility: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - name: Setup Node.js environment - uses: actions/setup-node@main - - - name: poetry cache - uses: actions/cache@v2 - with: - path: .venv - key: ${{ runner.os }}-${{ hashFiles('poetry.lock') }}-${{ matrix.python-version }} - - - name: Install dependencies - run: | - pip install poetry - poetry config --local virtualenvs.in-project true - poetry install --no-root --remove-untracked - npm install pa11y pa11y-reporter-junit - - - name: Start docs server - run: poetry run mkdocs serve & - - - name: Accessibility testing (Pa11y) - run: poetry run .github/workflows/pa11y.sh - - # leaving this out for now (there are too many warnings) - # - name: Upload Unit Test Results - # if: always() - # uses: actions/upload-artifact@v2 - # with: - # name: Unit Test Results (pa11y) - # path: reports/pa11y/*.xml - publish-test-results: + if: success() || failure() name: "Publish Unit Tests Results" - needs: [test, accessibility] + needs: test runs-on: ubuntu-latest - if: always() steps: - name: Download Artifacts