diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e1381bd..bc908bf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,15 +1,101 @@ -name: Test container build +name: Build, Lint, and Test on: push: branches: - master pull_request: - branches_ignore: [] + branches-ignore: [] + +env: + DOCKER_TAG_NAME: snakemake-tutorial jobs: + docker-build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Setup Buildx + uses: docker/setup-buildx-action@v3 + + - name: Lint Dockerfile + uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: Dockerfile + no-fail: true + + - name: Build Docker Image + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + tags: ${{ env.DOCKER_TAG_NAME }} + outputs: type=docker, dest=/tmp/${{ env.DOCKER_TAG_NAME }}.tar + + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.DOCKER_TAG_NAME }} + path: /tmp/${{ env.DOCKER_TAG_NAME }}.tar + + lint: + runs-on: ubuntu-latest + needs: docker-build + steps: + - name: Checkout Code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Buildx + uses: docker/setup-buildx-action@v3 + + - name: Lint Snakefile + uses: github/super-linter@v7 + env: + VALIDATE_ALL_CODEBASE: false + DEFAULT_BRANCH: master + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + VALIDATE_SNAKEMAKE_SNAKEFMT: true + + - name: Download Artifact + uses: actions/download-artifact@v4 + with: + name: snakemake-tutorial + path: /tmp + + - name: Load Docker Image + run: docker load -i /tmp/${{ env.DOCKER_TAG_NAME }}.tar + + - name: DryRun Snakefile + run: | + docker run -v $(pwd):/work -w /work ${{env.DOCKER_TAG_NAME}} \ + conda run -n ${{env.DOCKER_TAG_NAME}} snakemake -n + test: runs-on: ubuntu-latest + needs: docker-build steps: - - uses: actions/checkout@master - - run: docker build . \ No newline at end of file + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Setup Buildx + uses: docker/setup-buildx-action@v3 + + - name: Download Artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.DOCKER_TAG_NAME }} + path: /tmp + + - name: Load Docker Image + run: docker load -i /tmp/${{env.DOCKER_TAG_NAME}}.tar + + - name: Run Tests + run: | + docker run -v $(pwd):/work -w /work ${{env.DOCKER_TAG_NAME}} \ + conda run -n ${{env.DOCKER_TAG_NAME}} snakemake --cores 1 + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15f5c82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +calls +plots +sorted_reads +mapped_reads +.snakemake \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index c472fed..534d5ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM snakemake/snakemake:stable -ADD environment.yaml . +COPY environment.yaml . RUN conda create -n snakemake-tutorial --clone snakemake; \ conda env update -n snakemake-tutorial -f environment.yaml; RUN mkdir -p /tmp/conda -ENV CONDA_PKGS_DIRS /tmp/conda \ No newline at end of file +ENV CONDA_PKGS_DIRS=/tmp/conda \ No newline at end of file diff --git a/workflow/Snakefile b/workflow/Snakefile new file mode 100644 index 0000000..dcb194d --- /dev/null +++ b/workflow/Snakefile @@ -0,0 +1,56 @@ +SAMPLES = ["A", "B"] + + +rule all: + input: + "plots/quals.svg", + + +rule bwa_map: + input: + "data/genome.fa", + "data/samples/{sample}.fastq", + output: + "mapped_reads/{sample}.bam", + shell: + "bwa mem {input} | samtools view -Sb - > {output}" + + +rule samtools_sort: + input: + "mapped_reads/{sample}.bam", + output: + "sorted_reads/{sample}.bam", + shell: + "samtools sort -T sorted_reads/{wildcards.sample} " + "-O bam {input} > {output}" + + +rule samtools_index: + input: + "sorted_reads/{sample}.bam", + output: + "sorted_reads/{sample}.bam.bai", + shell: + "samtools index {input}" + + +rule bcftools_call: + input: + fa="data/genome.fa", + bam=expand("sorted_reads/{sample}.bam", sample=SAMPLES), + bai=expand("sorted_reads/{sample}.bam.bai", sample=SAMPLES), + output: + "calls/all.vcf", + shell: + "bcftools mpileup -f {input.fa} {input.bam} | " + "bcftools call -mv - > {output}" + + +rule plot_quals: + input: + "calls/all.vcf", + output: + "plots/quals.svg", + script: + "scripts/plot-quals.py" diff --git a/workflow/scripts/plot-quals.py b/workflow/scripts/plot-quals.py new file mode 100644 index 0000000..8483275 --- /dev/null +++ b/workflow/scripts/plot-quals.py @@ -0,0 +1,9 @@ +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +from pysam import VariantFile + +quals = [record.qual for record in VariantFile(snakemake.input[0])] +plt.hist(quals) + +plt.savefig(snakemake.output[0]) \ No newline at end of file