Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Github Action #21

Open
goerz opened this issue Mar 26, 2021 · 1 comment
Open

Add a Github Action #21

goerz opened this issue Mar 26, 2021 · 1 comment

Comments

@goerz
Copy link
Owner

goerz commented Mar 26, 2021

With the demise of Travis (#13), Github Actions is the default option for continuous integration. As of the recent renaming of the project from doctr-versions-info to docs-versions-info, the project is in fact using Github Actions to deploy its own documentation. However, the steps in the action are rather involved:

deploy_gh_pages:
name: Deploy documentation to gh-pages
if: always() && needs.build_docs.result == 'success' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))
runs-on: ubuntu-18.04
needs: [build_docs]
steps:
- uses: actions/setup-python@v2
name: Install Python 3.8
with:
python-version: 3.8
- name: Install deploy requirements
run: pip install git+https://github.com/goerz/docs_versions_menu.git@master#egg=docs_versions_menu
- name: Get branch name
shell: bash
run: |
echo ${{ github.ref }}
echo "BRANCH_NAME=$(echo ${GITHUB_REF##*/} | tr / -)" >> $GITHUB_ENV
cat $GITHUB_ENV
- uses: actions/checkout@v2
name: Check out gh-pages branch (full history)
with:
ref: gh-pages
fetch-depth: 0
- uses: actions/download-artifact@v2
name: Download documentation artifact
with:
name: docs
path: _docs
- name: Unzip html documentation
working-directory: _docs
shell: bash
run: |
unzip *.zip -d _unzip
mv _unzip/* _unzip/${{ env.BRANCH_NAME }}
- name: Rsync html documentation into place
run: rsync -av --delete _docs/_unzip/${{ env.BRANCH_NAME }}/ ./${{ env.BRANCH_NAME }}/
- name: Set download links
if: startsWith(github.ref, 'refs/tags/v')
run: |
echo "[html]: https://github.com/goerz/docs-versions-menu/releases/download/${{ env.BRANCH_NAME }}/docs-versions-menu-${{ env.BRANCH_NAME }}.zip" >> ./${{ env.BRANCH_NAME }}/_downloads
- name: Remove artifact files
shell: bash
run: rm -rf _docs
- name: Run docs-versions-menu
run: docs-versions-menu
env:
DOCS_VERSIONS_MENU_DEBUG: 'true'
DOCS_VERSIONS_MENU_VERSIONS: '(<branches> != (master, rtd-theme)), (<releases>)[:-1], rtd-theme, (<releases>)[-1], master'
DOCS_VERSIONS_MENU_LABEL: 'rtd-theme: v0.4.1 (rtd-theme)'
DOCS_VERSIONS_MENU_WARNING: 'unreleased: (<branches> != rtd-theme), <local-releases>'
- name: Get the previous commit message
id: get_previous_commit
run: |
git log --format=%B -n 1 | tee .git/_github_actions_commit_msg
echo ::set-output name=log::$(cat .git/_github_actions_commit_msg)
echo ::set-output name=lastline::$(cat .git/_github_actions_commit_msg | grep -v '^$' | tail -n1)
echo ::set-output name=author::$(git log --format=%an -n 1)
- name: Set git configuration
shell: bash
run: |
git config user.name github-actions
git config user.email [email protected]
- name: Commit changes
shell: bash
run: |
echo "Committing to gh-pages"
echo "# GIT ADD"
git add -A --verbose
echo "# GIT STATUS"
git status
echo "# GIT COMMIT"
if [[ "${{ steps.get_previous_commit.outputs.author }}" == "github-actions"* && "${{ steps.get_previous_commit.outputs.lastline }}" == *"${{ github.ref }}"* ]];
then
# we ammend if the previous commit was down by Github Actions and was based on the same branch/tag name
echo "Amending previous commit"
echo "Deployed from commit ${GITHUB_SHA} (${GITHUB_REF})" >> .git/_github_actions_commit_msg
git commit --verbose --amend -F .git/_github_actions_commit_msg
else
echo "Making new commit"
git commit --verbose -m "Auto-update from Github Actions Workflow" -m "Deployed from commit ${GITHUB_SHA} (${GITHUB_REF})"
fi
git log -n 1
- name: Push changes
run: git push --verbose --force

The question has come up why it's necessary to go through all these steps instead of deploying to gh-pages with an existing action. The reason is that doctr-versions-menu has to run on the gh-pages branch. Certainly, the deploy-to-github-pages action can handle all aspects uploading the Sphinx documentation to gh-pages. It does for Github Actions what Doctr did for Travis. However, it does not have the equivalent of Doctr's --command option that would allow to run docs-versions-menu on the gh-pages branch.

Thus, we we will have to create our own action for running doctr-versions-menu. The action is going to similar to the existing deploy actions.

In principle, Github Actions can be Docker or Javascript (Typescript) based. Typescript is faster and runs on more platforms. Hence, the deploy-to-github-pages action is written in Typescript. Unfortunately, I don't know Typescript, so this is a non-starter.

There is one action, actions-gh-pages, that was Docker-based in an older version 2. This seems like an excellent staring point to develop a docs-versions-menu action.

The action would simply run docs-versions-menu on the gh-pages branch, thus turning the entire job into two steps (deploying to github, and running docs_versions_menu)

@CAM-Gerlach
Copy link

Hey @goerz ; I'm far from an expert on any of this and sorry I never got around to providing feedback on drdoctr/doctr#351 ; though perhaps its for the better since I didn't hijack the thread further.

With regard to getting a simple but working implementation online, since the dependency requirements are minimal have you considered whether a composite action would work, at least as a cheap initial prototype? It might not be quite as robust, but it would presumably be faster, much quicker and less complex to implement, and allow you to reuse your existing action steps. This is how we do it locally, but you'd have to test to confirm there isn't a reason why a remotely-hosted composite action wouldn't work, since I haven't tried that myself, and I'm not sure its a good idea long-term, but it could work as a stopgap at least.

What you'd put in there really depends on how much you want to automate, vs. preserving flexibility for users. A minimal implementation would need to include the Install dependencies and Run docs-versions-menus steps, presumably taking the the values of any env vars (or variables within) that you'd expect to change as arguments, and presumably an optional path to the directory the deploy branch was cloned in to, if not the current. A more comprehensive implementation might also checkout the deploy branch (gh-pages by default) to a user-specified directory, and copy/rsync the built docs to a subdirectory of that checkout matching the current BRANCH_NAME. (However, as to whether this is really worthwhile, I suggest you read on).

The build steps prior to this would naturally be up to the user, and the 4 bespoke deploy steps could be replaced with one of the Github Pages deploy actions, which provide similar (though not entirely identical) capabilities, sufficient for the vast majority of usecases and covering many features these bespoke ones do not (unless you really needed the fine-grained amend handling).

Regarding your points on drdoctr/doctr#351

The reason why there are two jobs: I always want to build the documentation, even on pull-requests and topic branches, to make sure that it works. However, I only want to deploy to gh-pages from master and for tagged releases. It seemed easiest to separate these two things into different jobs, and to transfer documentation between them as a built-artifact

We had the same desire; we didn't want the deployment steps to run on pull-request, while not wanting the testing steps (particularly linkcheck, which had transient failures that shouldn't block deploy) to run on push to a release branch. Like you, we split them into two separate workflows, one for each. In addition, we used a local composite action to encapsulate the common docs setup and build steps, to reduce the duplication between workflows (and the install and build steps themselves were in turn encapsulated in bash scripts, to maximize commonality between CI providers, namely Github Actions and Netlify).

However, I'm still a little confused as to the reasons for splitting the deploy workflow into two jobs and wrangling build artifacts between them, given this requires around 8-ish total extra steps and substantial additional runtime. The workflow only runs on a push to begin with, and you can set it to only run on release branches/tags with on:, along with if at the job level (as you did). If you still want the build to run on every push, but not the deploy, you can use if and a variable to skip undesired steps.

It seemed like existing actions for deploying to Github Pages wouldn't be helping much, really only replacing the "rsync" step. [...] To be useful, the JamesIves/github-pages-deploy-action would need to have the option to run a command on the gh-pages branch after it deploys to it.

Actually, unless I'm mistaken, you could replace the last four steps (including the quite complex second to last) with either of the popular Github pages deploy actions, with only a small loss in functionality (the custom commit amend handling beyond either amending or not, and a few prints). You could simply tell the actions to deploy your checkout of the deploy branch to which you rsynced the updated version and ran docs-versions-menu, either as a new commit or an amended one, and with a custom Github username, password and commit message.

With those two changes alone, you'd condense two jobs and 22 steps down to 11 and one (and mostly the simpler ones), and that's without having to make a separate docs_version_menu action: checkout build branch, setup Python, apt install, pip install, build docs, checkout gh-pages branch, get branch name, rsync, set download links, run docs-versions-menu, deploy. A more typical user workflow, without the extra/bespoke steps, would be more like 8 steps, as apt install and set download links are not necessary for most use cases, and without them and the build artifact, the branch name is only needed one place.

In that context, the minimal docs-versions-menu Github Action described above is of little net gain; depending on how configurable you want the env vars to be, it might simplify the docs-versions-menu step modestly to not at all, and only avoids one extra dep in the initial pip install, so its still 8 steps. Adding automatic checkout and rsync is of somewhat more benefit, getting things down to 6 steps, though as those steps are only a few lines, they require additional config vars be fed to your action, it still isn't a huge net gain (though is still worth something).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants