Skip to content

Commit a27566c

Browse files
authored
Merge pull request #30 from icgc-argo/pre-issue29
added files for wfpm
2 parents 7d711f3 + 8f951f2 commit a27566c

8 files changed

Lines changed: 340 additions & 1 deletion

File tree

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
name: CI/CD
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- '*\@[0-9]+.[0-9]+.[0-9]+*' # package development branch
8+
9+
jobs:
10+
build:
11+
if: ${{ !contains(github.event.head_commit.message, '[no ci]') }}
12+
runs-on: ubuntu-latest
13+
outputs:
14+
branch: ${{ steps.get_pkg_info.outputs.branch }}
15+
pkg_name: ${{ steps.get_pkg_info.outputs.pkg_name }}
16+
pkg_ver: ${{ steps.get_pkg_info.outputs.pkg_ver }}
17+
docker_file: ${{ steps.get_pkg_info.outputs.docker_file }}
18+
repo_lowercase: ${{ steps.repo_lowercase.outputs.lowercase }}
19+
steps:
20+
- uses: actions/checkout@v2
21+
22+
- name: Set up Python 3.6
23+
uses: actions/setup-python@v2
24+
with:
25+
python-version: 3.6
26+
27+
- name: Extract package name and version from branch name
28+
id: get_pkg_info
29+
shell: bash
30+
run: |
31+
echo "::set-output name=branch::$(echo ${GITHUB_REF#refs/heads/})"
32+
PKG_NAME=$(echo ${GITHUB_REF#refs/heads/} | awk -F'@' '{print $1}')
33+
PKG_VER=$(echo ${GITHUB_REF#refs/heads/} | awk -F'@' '{print $2}')
34+
echo "::set-output name=pkg_name::$(echo $PKG_NAME)"
35+
echo "::set-output name=pkg_ver::$(echo $PKG_VER)"
36+
if [[ -f "./$PKG_NAME/Dockerfile" ]]; then
37+
echo "::set-output name=docker_file::$(echo ./$PKG_NAME/Dockerfile)"
38+
else
39+
echo "::set-output name=docker_file::"
40+
fi
41+
42+
- name: Login to GitHub Container Registry
43+
if: ${{ steps.get_pkg_info.outputs.branch != 'main' && steps.get_pkg_info.outputs.docker_file != ''}}
44+
uses: docker/login-action@v1
45+
with:
46+
registry: ghcr.io
47+
username: ${{ github.repository_owner }}
48+
password: ${{ secrets.CR_PAT }}
49+
50+
- id: repo_lowercase
51+
uses: ASzc/change-string-case-action@v1
52+
with:
53+
string: ${{ github.repository }}
54+
55+
- name: Build image
56+
if: ${{ steps.get_pkg_info.outputs.branch != 'main' && steps.get_pkg_info.outputs.docker_file != ''}}
57+
uses: docker/build-push-action@v2
58+
with:
59+
context: "./${{steps.get_pkg_info.outputs.pkg_name}}"
60+
file: "${{steps.get_pkg_info.outputs.docker_file}}"
61+
platforms: linux/amd64
62+
load: true
63+
tags: |
64+
ghcr.io/${{ steps.repo_lowercase.outputs.lowercase }}.${{ steps.get_pkg_info.outputs.pkg_name }}:${{ steps.get_pkg_info.outputs.pkg_ver }}
65+
66+
- name: Push image to ghcr.io
67+
id: push_to_ghcr
68+
if: ${{ steps.get_pkg_info.outputs.branch != 'main' && steps.get_pkg_info.outputs.docker_file != ''}}
69+
shell: bash
70+
run: |
71+
docker push ghcr.io/${{ steps.repo_lowercase.outputs.lowercase }}.${{ steps.get_pkg_info.outputs.pkg_name }}:${{ steps.get_pkg_info.outputs.pkg_ver }} | tee ./ghcr.io.stdout
72+
IMAGE_SHA=$(cat ./ghcr.io.stdout | tr ' ' '\n' | grep 'sha256:' | awk -F':' '{print $2}')
73+
echo "::set-output name=image_sha256::$(echo ${IMAGE_SHA})"
74+
echo "::set-output name=created_at::$(date -u +%FT%TZ)"
75+
76+
77+
test-and-release:
78+
runs-on: ubuntu-latest
79+
needs: [build]
80+
steps:
81+
- uses: actions/checkout@v2
82+
83+
- name: Set up Python 3.6
84+
uses: actions/setup-python@v2
85+
with:
86+
python-version: 3.6
87+
88+
- name: Install dependencies
89+
run: |
90+
python -m pip install --upgrade pip
91+
pip install wfpm
92+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
93+
if [ -f requirements-test.txt ]; then pip install -r requirements-test.txt; fi
94+
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi
95+
96+
- name: Install Nextflow
97+
run: |
98+
wget --tries=10 -qO- https://get.nextflow.io | bash
99+
sudo chmod 755 nextflow
100+
sudo mv nextflow /usr/local/bin/
101+
102+
- name: "Login to GitHub Container Registry" # normally shouldn't need to login, but new image when just created is private
103+
uses: docker/login-action@v1
104+
with:
105+
registry: ghcr.io
106+
username: ${{ github.repository_owner }}
107+
password: ${{ secrets.CR_PAT }}
108+
109+
- name: Run tests for all packages
110+
if: ${{ needs.build.outputs.branch == 'main' }}
111+
run: |
112+
wfpm test
113+
114+
- name: Run tests for the current package only
115+
if: ${{ needs.build.outputs.branch != 'main' }}
116+
run: |
117+
cd ./${{needs.build.outputs.pkg_name}}
118+
wfpm test
119+
120+
- name: Check whether to proceed with release
121+
id: to_release
122+
run: |
123+
if [[ \
124+
"${{ github.event.head_commit.message }}" = "Merge"[[:space:]]"pull"[[:space:]]"request"* && \
125+
"${{ github.event.head_commit.message }}" = *"@"* && \
126+
"${{ github.event.head_commit.message }}" = *"[release]"* && \
127+
"${{ needs.build.outputs.branch }}" = 'main'
128+
]]; then
129+
echo "::set-output name=release::$(echo Y)"
130+
else
131+
echo "::set-output name=release::$(echo N)"
132+
fi
133+
134+
- name: Extract package name and version from commit message
135+
if: ${{ steps.to_release.outputs.release == 'Y' }}
136+
id: get_pkg_info
137+
shell: bash
138+
run: |
139+
MERGED_BR=$(echo -e '${{ github.event.head_commit.message }}' | \
140+
{ grep '^Merge pull request'||:; } | tr ' ' '\n' |{ grep '@'||:; } | awk -F'/' '{print $2}')
141+
PKG_NAME=$(echo $MERGED_BR | awk -F'@' '{print $1}')
142+
PKG_VER=$(echo $MERGED_BR | awk -F'@' '{print $2}')
143+
echo "::set-output name=pkg_name::$(echo ${PKG_NAME})"
144+
echo "::set-output name=pkg_ver::$(echo ${PKG_VER})"
145+
if [[ -f "./$PKG_NAME/Dockerfile" ]]; then
146+
echo "::set-output name=docker_file::$(echo ./$PKG_NAME/Dockerfile)"
147+
echo "::set-output name=docker_image::$(echo ghcr.io/${{ needs.build.outputs.repo_lowercase }}.$PKG_NAME:$PKG_VER)"
148+
else
149+
echo "::set-output name=docker_file::"
150+
echo "::set-output name=docker_image::"
151+
fi
152+
153+
- name: Prepare package release tarball
154+
id: prep_assets
155+
if: ${{ steps.to_release.outputs.release == 'Y' }}
156+
shell: bash
157+
run: |
158+
./scripts/cleanup_temp_files.sh # just in case
159+
PKG_TAR=${{ steps.get_pkg_info.outputs.pkg_name }}.v${{ steps.get_pkg_info.outputs.pkg_ver }}.tar.gz
160+
pushd ${{ steps.get_pkg_info.outputs.pkg_name }}
161+
tar --exclude=wfpr_modules --dereference -czvf ../$PKG_TAR .
162+
popd
163+
echo "::set-output name=pkg_tar::$(echo ${PKG_TAR})"
164+
echo "::set-output name=pkg_tar_sha::$(sha256sum ${PKG_TAR} |awk '{print $1}')"
165+
echo "::set-output name=pkg_tar_size::$(ls -l ${PKG_TAR} |awk '{print $5}')"
166+
echo "::set-output name=created_at::$(date -u +%FT%TZ)"
167+
168+
- name: Create release
169+
id: create_release
170+
if: ${{ steps.to_release.outputs.release == 'Y' }}
171+
uses: actions/create-release@v1
172+
env:
173+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
174+
with:
175+
tag_name: ${{ steps.get_pkg_info.outputs.pkg_name }}.v${{ steps.get_pkg_info.outputs.pkg_ver }}
176+
release_name: ${{ steps.get_pkg_info.outputs.pkg_name }}.v${{ steps.get_pkg_info.outputs.pkg_ver }}
177+
body: |
178+
* Release `${{ steps.get_pkg_info.outputs.pkg_name }}.v${{ steps.get_pkg_info.outputs.pkg_ver }}` (${{ github.sha }})
179+
* Package `${{ steps.prep_assets.outputs.pkg_tar }}` (sha256: `${{ steps.prep_assets.outputs.pkg_tar_sha }}`)
180+
draft: false
181+
prerelease: false
182+
183+
- name: Prepare in pkg-release.json
184+
if: ${{ steps.to_release.outputs.release == 'Y' }}
185+
shell: bash
186+
run: |
187+
WFPM_VER=$(wfpm -v | cut -d ' ' -f 2)
188+
if [[ '${{ steps.get_pkg_info.outputs.docker_file }}' != '' ]]; then
189+
docker pull ${{ steps.get_pkg_info.outputs.docker_image }} | tee image.info
190+
IMAGE_SHA=$(cat ./image.info | tr ' ' '\n' | grep 'sha256:' | awk -F':' '{print $2}')
191+
else
192+
IMAGE_SHA=$(echo)
193+
fi
194+
195+
# temporary solution
196+
TAG="${{ steps.get_pkg_info.outputs.pkg_name }}.v${{ steps.get_pkg_info.outputs.pkg_ver }}"
197+
./scripts/prepare_package_release_json.py -p ${{ steps.get_pkg_info.outputs.pkg_name }}/pkg.json -d \
198+
"
199+
{
200+
\"_release\": {
201+
\"created\": \"${{ steps.prep_assets.outputs.created_at }}\",
202+
\"hash\": {
203+
\"checksum_type\": \"sha1\",
204+
\"checksume\": \"${{ github.sha }}\"
205+
},
206+
\"tag\": \"$TAG\",
207+
\"assets\": [
208+
{
209+
\"filename\": \"$TAG.tar.gz\",
210+
\"download_url\": \"https://github.com/${{ github.repository }}/releases/download/$TAG/$TAG.tar.gz\",
211+
\"checksum\": \"${{ steps.prep_assets.outputs.pkg_tar_sha }}\",
212+
\"checksum_type\": \"sha256\",
213+
\"size\": ${{ steps.prep_assets.outputs.pkg_tar_size }}
214+
},
215+
{
216+
\"_NOTE_\": \"this file\",
217+
\"filename\": \"pkg-release.json\",
218+
\"download_url\": \"https://github.com/${{ github.repository }}/releases/download/$TAG/pkg-release.json\",
219+
\"checksum\": null,
220+
\"checksum_type\": null,
221+
\"size\": null
222+
}
223+
]
224+
},
225+
\"_image_digest\": {
226+
\"checksum\": \"$IMAGE_SHA\",
227+
\"checksum_type\": \"sha256\"
228+
},
229+
\"_wfpm_ver\": \"$WFPM_VER\"
230+
}
231+
" > pkg-release.json
232+
233+
- name: Upload package release tarball
234+
if: ${{ steps.to_release.outputs.release == 'Y' }}
235+
uses: actions/upload-release-asset@v1
236+
env:
237+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
238+
with:
239+
upload_url: ${{ steps.create_release.outputs.upload_url }}
240+
asset_path: ./${{ steps.prep_assets.outputs.pkg_tar }}
241+
asset_name: ${{ steps.prep_assets.outputs.pkg_tar }}
242+
asset_content_type: application/zip
243+
244+
- name: Upload package release json
245+
if: ${{ steps.to_release.outputs.release == 'Y' }}
246+
uses: actions/upload-release-asset@v1
247+
env:
248+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
249+
with:
250+
upload_url: ${{ steps.create_release.outputs.upload_url }}
251+
asset_path: ./pkg-release.json
252+
asset_name: pkg-release.json
253+
asset_content_type: application/json

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,9 @@ reference
1010
out
1111
reports
1212
remote_reports
13-
params.json
13+
params.json
14+
.log
15+
.python-version
16+
.nextflow*
17+
outdir
18+
wfpr_modules/github.com/*/*/*/tests

.wfpm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
project_name: nextflow-data-processing-utility-tools
2+
license: Apache License 2.0
3+
repo_type: git
4+
repo_server: github.com
5+
repo_account: icgc-argo

LICENSE-short

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright (c) 2020-2021, Ontario Institute for Cancer Research
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

nextflow.config

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
manifest {
2+
homePage = 'https://github.com/icgc-argo/nextflow-data-processing-utility-tools'
3+
description = 'SONG/SCORE download/upload packages'
4+
nextflowVersion = '>=20.10'
5+
}
6+
17
docker {
28
enabled = true
9+
runOptions = '-u \$(id -u):\$(id -g)'
310
}

scripts/cleanup_temp_files.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
for f in `find . -type d |egrep '(/work$)|(/.nextflow$)|(/outdir$)|(.nextflow.log)'`; do
4+
echo remove $f;
5+
rm -fr $f;
6+
done
7+
8+
for f in `find . -type f |egrep '\.nextflow\.log'`; do
9+
echo remove $f;
10+
rm $f;
11+
done
12+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python3
2+
3+
# this is a temporary solution
4+
5+
import argparse
6+
import json
7+
8+
9+
def update_image_digest(package_meta, release_meta_str):
10+
with open(package_meta, 'r') as f:
11+
package_meta = json.load(f)
12+
13+
release_meta = json.loads(release_meta_str)
14+
15+
if 'container' in package_meta:
16+
package_meta['container']['_image_digest'] = release_meta['_image_digest']
17+
package_meta['_release'] = release_meta['_release']
18+
package_meta['_wfpm_ver'] = release_meta.get('_wfpm_ver')
19+
20+
return package_meta
21+
22+
23+
if __name__ == '__main__':
24+
parser = argparse.ArgumentParser(description='Update pkg.json to generate pkg-release.json ')
25+
parser.add_argument('-p', dest='package_meta', type=str, required=True)
26+
parser.add_argument('-d', dest='release_meta_str', type=str, required=True)
27+
args = parser.parse_args()
28+
29+
updated_meta = update_image_digest(
30+
args.package_meta,
31+
args.release_meta_str
32+
)
33+
34+
print(json.dumps(updated_meta, indent=4, sort_keys=True))

wfpr_modules/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Workflow Package Installation Directory
2+
3+
This directory contains all dependent workflow packages that are to be installed by the package
4+
management tool: [WFPM](https://github.com/icgc-argo/wfpm) (WorkFlow Package Manager). Please
5+
do NOT modify contents under this directory manually.
6+
7+
Ideally the packages installed in this directory do not need to be checked into git repo, similar
8+
to NPM's `node_modules` directory. Instead, all dependent packages/modules are to be installed
9+
at deployment time. But let's keep the modules checked into git repo before deployment time
10+
installation is supported.

0 commit comments

Comments
 (0)