Skip to content

Continuous integration #682

Continuous integration

Continuous integration #682

Workflow file for this run

name: Continuous integration
on:
push:
workflow_dispatch:
inputs:
simulatorVersion:
description: New version of the underlying simulation tool (e.g., '1.5.6')
required: true
forceRelease:
description: Type "true" (case sensitive) to ensure a release will happen (use carefully!)
required: true
schedule:
- cron: "0 0 * * *"
jobs:
continuousIntegration:
name: Update simulator version, lint, test, compile documentation, and release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get-tagged-version.outputs.version }}
simulatorId: ${{ steps.get-docker-image-tag.outputs.simulatorId }}
simulatorVersion: ${{ steps.get-docker-image-tag.outputs.simulatorVersion }}
simulatorName: ${{ steps.get-docker-image-tag.outputs.simulatorName }}
dockerImageBaseUrl: ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}
dockerRegistry: ${{ steps.get-docker-image-tag.outputs.dockerRegistry }}
docsChanged: ${{ steps.commit-docs.outputs.docsChanged }}
defaults:
run:
shell: bash
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
#*******************************************#
#* Validation *#
#*******************************************#
#############################################
## Get Last Release's Info
#############################################
- name: Gets latest created release info
id: latest_release_info
uses: fangqiuming/latest-release-version@v1.1.1
#############################################
## If Tagged, Set the `_version.py` File to Reflect it
#############################################
- name: Align Version with tag
id: get-tagged-version
if: startsWith(github.ref, 'refs/tags/')
run: |
taggedVersion=$(echo $(echo ${{ github.ref }} | cut -d '/' -f 3))
echo "processing `$taggedVersion`"
echo "__version__ = '${taggedVersion}'" > biosimulators_copasi/_version.py
echo "version=${taggedVersion}" >> "$GITHUB_OUTPUT"
echo $(cat biosimulators_copasi/_version.py)
#############################################
## Install package and its dependencies
#############################################
# install package
- name: Set up the environment
uses: ./.github/actions/setup-poetry-env
with:
python-version: "3.10"
#############################################
## Check if we need to perform a release
#############################################
- id: check-new-release
name: Check if we need to perform a release
run: |
# We version the containers with the `biosimulators_copasi` version, but list the version
# online as the COPASI version within the container.
taggedVersion="${{ steps.get-tagged-version.outputs.version }}"
copasiVersion=$(poetry -q run python -c "import COPASI; print(COPASI.__version__)")
echo "copasiVersion=$copasiVersion" >> "$GITHUB_OUTPUT"
echo "copasiVersion=$copasiVersion"
bioSimVersion=$(poetry -q run python -c "import biosimulators_copasi as bsc; print(bsc.__version__)")
echo "bioSimVersion=$bioSimVersion" >> "$GITHUB_OUTPUT"
echo "bioSimVersion=$bioSimVersion"
oldBioSimVersion=${{ steps.latest_release_info.outputs.tag_name }}
echo "oldBioSimVersion=$oldBioSimVersion"
if [[ $oldBioSimVersion < $bioSimVersion ]] && ! [[ -z $taggedVersion ]]; then
echo "needDeploy=true" >> "$GITHUB_OUTPUT"
echo "Deploy will be performed!"
else
echo "needDeploy=false" >> "$GITHUB_OUTPUT"
echo "Deploy will NOT be performed:"
# Get an idea of why we will not deploy
if [[ $oldBioSimVersion > $bioSimVersion ]]; then
echo "Version is not newer than existing version"
fi
if [[ $oldBioSimVersion == $bioSimVersion ]]; then
echo "Old and new versions are the same"
fi
if [[ -z $taggedVersion ]]; then
echo "This is not a tagged action; push a new tag to release."
fi
fi
#############################################
## Lint and Test
#############################################
- name: Lint the package
run: poetry run python -m flake8
- name: Run the tests
run: poetry run python -m pytest tests/ --cov=./biosimulators_copasi/ --cov-report=xml
- name: Upload the coverage report to Codecov
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
file: ./coverage.xml
#############################################
## Compile documentation
#############################################
- name: Install the requirements for compiling the documentation
run: poetry install --with docs
- name: Compile the documentation
run: |
poetry run sphinx-apidoc . pyproject.toml --output-dir docs-src/source --force --module-first --no-toc
mkdir -p docs-src/_static
poetry run sphinx-build docs-src docs
#############################################
## Check for Deploy, Stop if not Deploying (disabled due to the fact it cancels, not passes)
#############################################
# - name: Cancel build if not for release
# uses: andymckay/cancel-action@0.2
# if: steps.check-new-release.outputs.needDeploy != 'true'
#*******************************************#
#* Release *#
#*******************************************#
#############################################
# Give nice, clear heads up in GitHub Action that We are Deploying
#############################################
- name: Start the Deploy Process
if: steps.check-new-release.outputs.needDeploy == 'true'
run: echo 'Beginning Deploy Steps'
#############################################
## Form-fill the versions to the container, `pyproject.toml`, and part of `biosimulators.json`
#############################################
- name: Update versioning in "Dockerfile", "pyproject.toml", and part of "biosimulators.json"
if: steps.check-new-release.outputs.needDeploy == 'true'
run: |
copasiVersion=${{ steps.check-new-release.outputs.copasiVersion }}
bioSimVersion=${{ steps.check-new-release.outputs.bioSimVersion }}
sed -i -E "s/ARG SIMULATOR_VERSION=([^ \n]+|\".*?\")/ARG SIMULATOR_VERSION=\"${copasiVersion}\"/" Dockerfile
sed -i -E "s/ARG VERSION=([^ \n]+|\".*?\")/ARG VERSION=\"${bioSimVersion}\"/" Dockerfile
sed -i -E "s/^version\s+=\s+(\".*?\")/version = \"${bioSimVersion}\"/mg" pyproject.toml
sed -i -E "s/__COPASI_VERSION__/${copasiVersion}/g" biosimulators.json
poetry update
#############################################
# Create PyPI release
#############################################
- name: Create PyPI release
if: steps.check-new-release.outputs.needDeploy == 'true'
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
run: |
echo''
# Install pandoc
# sudo apt-get update -y
# sudo apt-get install -y --no-install-recommends wget
# wget https://github.com/jgm/pandoc/releases -O /tmp/pandocVersions.html
# urlPart=`grep "\.deb" /tmp/pandocVersions.html | head -n 1 | cut -d'/' -f2-7 | cut -d'"' -f1`
# wget "https://github.com/$urlPart" -O /tmp/pandoc.deb
# sudo dpkg -i /tmp/pandoc.deb
# rm /tmp/pandocVersions.html
# rm /tmp/pandoc.deb
# Convert README to .rst format
# pandoc --from=gfm --output=README.rst --to=rst README.md
# Build and Publish
poetry build
poetry publish --no-interaction --username __token__ --password $POETRY_PYPI_TOKEN_PYPI
#############################################
## Build and Push Docker image
#############################################
- id: get-docker-image-tag
name: Determine Docker image tag
if: steps.check-new-release.outputs.needDeploy == 'true'
run: |
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends jq
SIMULATOR_ID=$(jq -r '.id' biosimulators.json)
SIMULATOR_VERSION=$(jq -r '.version' biosimulators.json)
SIMULATOR_NAME=$(jq -r '.name' biosimulators.json)
IMAGE_BASE_URL=$(jq -r '.image.url' biosimulators.json | cut -d : -f 1)
DOCKER_REGISTRY=$(echo $IMAGE_BASE_URL | cut -d / -f 1)
echo "simulatorId=${SIMULATOR_ID}" >> "$GITHUB_OUTPUT"
echo "simulatorVersion=${SIMULATOR_VERSION}" >> "$GITHUB_OUTPUT"
echo "simulatorName=${SIMULATOR_NAME}" >> "$GITHUB_OUTPUT"
echo "dockerImageBaseUrl=${IMAGE_BASE_URL}" >> "$GITHUB_OUTPUT"
echo "dockerRegistry=${DOCKER_REGISTRY}" >> "$GITHUB_OUTPUT"
echo "simulatorId=${SIMULATOR_ID}"
echo "simulatorVersion=${SIMULATOR_VERSION}"
echo "simulatorName=${SIMULATOR_NAME}"
echo "dockerImageBaseUrl=${IMAGE_BASE_URL}"
echo "dockerRegistry=${DOCKER_REGISTRY}"
- name: Build Docker image
if: steps.check-new-release.outputs.needDeploy == 'true'
run: |
REVISION=$(git rev-parse HEAD)
CREATED=$(date --rfc-3339=seconds | sed 's/ /T/')
docker build \
--label org.opencontainers.image.source=https://github.com/${{ github.repository }} \
--label org.opencontainers.image.revision=${REVISION} \
--label org.opencontainers.image.created=${CREATED} \
--build-arg VERSION=${{ steps.get-tagged-version.outputs.version }} \
--build-arg SIMULATOR_VERSION=${{ steps.get-docker-image-tag.outputs.simulatorVersion }} \
--tag ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}:${{ steps.check-new-release.outputs.copasiVersion }} \
--tag ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}:latest \
.
- name: Push Docker image
if: steps.check-new-release.outputs.needDeploy == 'true'
run: |
docker login ${{ steps.get-docker-image-tag.outputs.dockerRegistry }} \
--username ${{ secrets.DOCKER_REGISTRY_USERNAME }} \
--password ${{ secrets.DOCKER_REGISTRY_TOKEN }}
docker push ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}:${{ steps.get-docker-image-tag.outputs.simulatorVersion }}
if [[ "${{ github.ref }}" =~ ^refs/tags/ ]] || [ "${{ steps.check-new-release.outputs.simulatorVersionLatest }}" == "true" ]; then
docker push ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}:latest
fi
#############################################
## Form-fill the digest portion of "biosimulators.json"
#############################################
- name: Update versioning in "biosimulators.json"
if: steps.check-new-release.outputs.needDeploy == 'true'
run: |
containerLabel=${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}:${{ steps.get-docker-image-tag.outputs.simulatorVersion }}
docker pull $containerLabel
imageId=$(docker image ls | grep ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }} | grep ${{ steps.get-docker-image-tag.outputs.simulatorVersion }} | awk '{ print $3; }')
dockerDigest=$(docker inspect --format='{{index .RepoDigests 0}}' $imageId | cut -d '@' -f 2)
sed -i -E "s/__CONTAINER_DIGEST__/${dockerDigest}/g" biosimulators.json
#############################################
# Submit to BioSimulators registry
#############################################
- name: Submit to BioSimulators registry
if: steps.check-new-release.outputs.needDeploy == 'true'
run: |
REVISION=$(git rev-parse HEAD)
IMAGE_DIGEST=$(docker image inspect ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}:${{ steps.get-docker-image-tag.outputs.simulatorVersion }} | jq -r '.[0].RepoDigests[0]' | cut -d "@" -f 2-)
curl \
-X POST \
-u ${{ secrets.GH_ISSUE_USERNAME }}:${{ secrets.GH_ISSUE_TOKEN }} \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/biosimulators/Biosimulators/issues \
-d "{\"labels\": [\"Validate/submit simulator\"], \"title\": \"Submit ${{ steps.get-docker-image-tag.outputs.simulatorName }} ${{ steps.get-docker-image-tag.outputs.simulatorVersion }}\", \"body\": \"---\nid: ${{ steps.get-docker-image-tag.outputs.simulatorId }}\nversion: ${{ steps.get-docker-image-tag.outputs.simulatorVersion }}\nspecificationsUrl: https://raw.githubusercontent.com/${{ github.repository }}/${REVISION}/biosimulators.json\nspecificationsPatch:\n version: ${{ steps.get-docker-image-tag.outputs.simulatorVersion }}\n image:\n url: ${{ steps.get-docker-image-tag.outputs.dockerImageBaseUrl }}:${{ steps.get-docker-image-tag.outputs.simulatorVersion }}\n digest: \\\"${IMAGE_DIGEST}\\\"\nvalidateImage: true\ncommitSimulator: true\n\n---\"}"
#############################################
# If new tag, commit and push documentation
#############################################
- id: commit-docs
name: Commit the compiled documentation
if: steps.check-new-release.outputs.needDeploy == 'true'
run: |
git config --local user.email "biosimulators.daemon@gmail.com"
git config --local user.name "biosimulatorsdaemon"
git config pull.rebase false
# Need to check if we did the release on `dev` or not, very important!
commitHash=$(git rev-parse ${{ steps.get-tagged-version.outputs.version }}^{commit})
onDev=$(git branch -a --contains $commitHash | grep remotes/origin/master)
if [[ -z $onDev ]]; then
git stash
git checkout dev
git pull origin dev
set +e
git stash pop
git add docs
git commit -m "Updating compiled documentation"
git checkout .
git clean -f -d
if [[ $? = 0 ]]; then
docsChanged=1
else
docsChanged=0
fi
else
docsChanged=0
fi
echo "docsChanged=$docsChanged" >> "$GITHUB_OUTPUT"
- name: Push the compiled documentation
if: steps.commit-docs.outputs.docsChanged == '1'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: dev
#############################################
# Create GitHub release
#############################################
- name: Create GitHub release
uses: actions/create-release@v1
if: steps.check-new-release.outputs.needDeploy == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.get-tagged-version.outputs.version }}
release_name: Release ${{ steps.get-tagged-version.outputs.version }}
#############################################
## Commit and push new version of simulator
#############################################
# # If new version of simulator, commit and push the new version
# - name: Commit the revised version of the simulator
# if: steps.check-new-release.outputs.needDeploy == 'true'
# run: |
# git config --local user.email "biosimulators.daemon@gmail.com"
# git config --local user.name "biosimulatorsdaemon"
# git config pull.rebase false
# git stash -- biosimulators.json Dockerfile
# git clean -f -d
# git checkout .
# git pull
# git stash pop
# git add biosimulators.json Dockerfile
# git commit -m "Updating version of simulator"
#
# - name: Push the revised version of the simulator
# if: steps.check-new-release.outputs.simulatorVersion && steps.check-new-release.outputs.simulatorVersionLatest == 'true'
# uses: ad-m/github-push-action@master
# with:
# github_token: ${{ secrets.GITHUB_TOKEN }}
# branch: ${{ github.ref }}