Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/build-gradle-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
jobs:
build-gradle-project:
env:
IMAGE_TAG: 1.11.0
IMAGE_TAG: 1.12.0
runs-on: ubuntu-latest
steps:
- name: Get branch names
Expand All @@ -26,7 +26,7 @@ jobs:
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
with:
gradle-version: 8.5
gradle-version: 8.14

- name: Login to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
Expand All @@ -36,15 +36,15 @@ jobs:

- name: Run build with Gradle Wrapper
run: |
./gradlew build docker
./gradlew bootBuildImage

- name: Push to Docker Hub if branch is develop
if: steps.branch-names.outputs.current_branch == 'develop'
run: |
docker push "kingstonduo/hydra-data:$IMAGE_TAG"
docker push "kingstonduo/hydra-data:${{env.IMAGE_TAG}}"

- name: Push to Docker Hub if branch is not develop
if: ${{ !steps.branch-names.outputs.current_branch == 'develop' }}
if: steps.branch-names.outputs.current_branch != 'develop'
run: |
docker push "kingstonduo/hydra-data:${{ steps.branch-names.outputs.current_branch }}"
Comment on lines 41 to 49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect getCurrentGitBranch() and verify whether the workflow sets up an attached branch before bootBuildImage runs.
rg -nP -C2 'getCurrentGitBranch|rev-parse|bootBuildImage' build.gradle
rg -nP -C2 'checkout|branch' .github/workflows/build-gradle-project.yml

Repository: KPMP/hydra-data

Length of output: 1699


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect workflow triggers and checkout configuration
sed -n '1,120p' .github/workflows/build-gradle-project.yml | nl -ba

echo "---- checkout block ----"
rg -n "uses: actions/checkout@v3" -n .github/workflows/build-gradle-project.yml -n
# Print 30 lines around checkout to see if it has inputs like ref/fetch-depth
python3 - <<'PY'
import itertools, re, pathlib
p = pathlib.Path(".github/workflows/build-gradle-project.yml")
lines = p.read_text().splitlines()
for i,l in enumerate(lines):
    if "uses: actions/checkout@v3" in l:
        start=max(0,i-15); end=min(len(lines), i+25)
        for j in range(start,end):
            print(f"{j+1:4d}:{lines[j]}")
        break
PY

echo "---- get/usage of IMAGE_TAG ----"
rg -n "IMAGE_TAG" .github/workflows/build-gradle-project.yml

Repository: KPMP/hydra-data

Length of output: 102


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- workflow header (first 120 lines) ----"
sed -n '1,120p' .github/workflows/build-gradle-project.yml | cat -n

echo "---- find triggers ----"
rg -n "^(on:|name:|jobs:)" .github/workflows/build-gradle-project.yml -n

echo "---- checkout block with context ----"
python3 - <<'PY'
from pathlib import Path
p = Path(".github/workflows/build-gradle-project.yml")
lines = p.read_text().splitlines()
for i,l in enumerate(lines):
    if "uses: actions/checkout@v3" in l:
        start=max(0,i-15); end=min(len(lines), i+35)
        for j in range(start,end):
            print(f"{j+1:4d}:{lines[j]}")
        break
PY

echo "---- checkout 'with' keys (if any) ----"
rg -n "with:|ref:|fetch-depth:" .github/workflows/build-gradle-project.yml

Repository: KPMP/hydra-data

Length of output: 3929


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show full getCurrentGitBranch and bootBuildImage section
rg -n "def getCurrentGitBranch\\(\\)|bootBuildImage\\s*\\{" build.gradle
python3 - <<'PY'
from pathlib import Path
p = Path("build.gradle")
lines = p.read_text().splitlines()
# print around getCurrentGitBranch
for i,l in enumerate(lines):
    if "def getCurrentGitBranch" in l:
        start=max(0,i-5); end=min(len(lines), i+60)
        for j in range(start,end):
            print(f"{j+1:4d}:{lines[j]}")
        break
PY

Repository: KPMP/hydra-data

Length of output: 1195


🌐 Web query:

actions/checkout v3 detached HEAD default behavior push event rev-parse --abbrev-ref HEAD

💡 Result:

In GitHub Actions, with actions/checkout v3, when the workflow is triggered by a push and you do not explicitly set ref, the action checks out the commit for the event in detached HEAD mode (so git rev-parse --abbrev-ref HEAD prints HEAD, not a branch name). This detached-head behavior is because the action checks out a specific commit/ref rather than creating/checking out a local branch by default.[1][2] What git rev-parse --abbrev-ref HEAD returns: - In detached HEAD state, --abbrev-ref cannot resolve a “current branch” symbolic ref, so it outputs HEAD (i.e., the name of the commit-ish you’re on).[1][3] How to get the branch name for a push event (recommended): - Use GitHub context variables rather than parsing git metadata. For example, for push workflows you can use GITHUB_REF_NAME (or GITHUB_REF) to get the branch/ref that triggered the workflow. (This avoids relying on the detached-HEAD checkout that actions/checkout performs.)[2] If you truly need a local branch in the runner: - You can create/switch to a branch after checkout (e.g., using git switch -c <name>), but note this is a separate step and doesn’t change that checkout itself happens detached.[2] Notes on other checkout-related defaults (unrelated to the detached HEAD behavior): - actions/checkout fetches only a single commit by default (unless you set fetch-depth). It documents fetch-depth and that 0 means fetch all history.[4][5]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for version definition(s)
rg -n "^[[:space:]]*version[[:space:]]*=|project\\.version\\b|version\\s+['\"]" build.gradle gradle.properties **/gradle.properties || true

# If build.gradle is big, also show the top 120 lines
sed -n '1,140p' build.gradle | cat -n

Repository: KPMP/hydra-data

Length of output: 3100


Critical: Docker push tag likely mismatches Gradle-built image tag (detached HEAD).

bootBuildImage tags the image as kingstonduo/hydra-data: + getCurrentGitBranch(), and getCurrentGitBranch() runs git rev-parse --abbrev-ref HEAD. With actions/checkout@v3 (no ref:) on on: push, the checkout is in detached-HEAD by default, so rev-parse --abbrev-ref HEAD returns HEAD and the built image tag becomes kingstonduo/hydra-data:HEAD (not the branch name).
As a result, both Docker Hub push steps can fail: the develop step pushes ...:${{ env.IMAGE_TAG }} (1.12.0) and the non-develop step pushes ...:${{ steps.branch-names.outputs.current_branch }} (e.g., feature/...)—neither matches ...:HEAD.

🧰 Tools
🪛 zizmor (1.25.2)

[info] 49-49: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM alpine:3.19.1
FROM alpine:3.22.4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Dockerfile is now orphaned by the migration.

With the move to ./gradlew bootBuildImage (Paketo buildpacks) and the removal of the unpack task, nothing in the build now produces target/dependency/BOOT-INF/..., so this Dockerfile can no longer be built successfully. Bumping the base image to alpine:3.22.4 updates a file that is effectively dead code. Suggest removing the Dockerfile (and skipping the alpine bump altogether) unless it is still intended to support a separate, documented workflow.

Note: the Trivy "USER should not be root" finding is moot if the file is removed; if you choose to keep the Dockerfile, it should be addressed by adding a non-root USER directive before ENTRYPOINT.

🧰 Tools
🪛 Trivy (0.69.3)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)


RUN apk update && \
apk upgrade
Expand Down
31 changes: 11 additions & 20 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:3.2.2")
classpath("org.springframework.boot:spring-boot-gradle-plugin:4.0.6")
}
}

plugins {
id 'com.palantir.docker' version '0.35.0'
id 'org.springframework.boot' version '3.2.2'
id 'org.springframework.boot' version '4.0.6'
}

group='kingstonduo'
version='1.11.0'
version='1.12.0'


apply plugin: 'java'
Expand All @@ -37,29 +36,20 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-graphql'
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'com.mysql:mysql-connector-j:8.3.0'
implementation 'org.apache.commons:commons-text:1.12.0'

implementation 'com.graphql-java:graphql-spring-boot-starter:5.0.2'
implementation 'com.graphql-java:graphiql-spring-boot-starter:5.0.2'
implementation 'com.graphql-java:graphql-java-tools:5.2.4'

testImplementation('org.mockito:mockito-junit-jupiter:3.12.4')
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework:spring-test:5.2.25.RELEASE'
testImplementation 'org.mockito:mockito-core'
}

springBoot {
mainClass = "org.kpmp.Application"
}

task unpack(type: Copy) {
dependsOn bootJar
from(zipTree(tasks.bootJar.outputs.files.singleFile))
into("build/dependency")
}

def getCurrentGitBranch() {
if (project.hasProperty('tag')) {
def tagValue = project.property('tag')
Expand All @@ -83,9 +73,10 @@ def getCurrentGitBranch() {
}
}


docker {
name "kingstonduo/hydra-data:" + getCurrentGitBranch()
copySpec.from(tasks.unpack.outputs).into("dependency")
buildArgs(['DEPENDENCY': "dependency"])
bootBuildImage {
imageName = "kingstonduo/hydra-data:" + getCurrentGitBranch()
createdDate = "now"
}

// Docker image building is now handled by Spring Boot's bootBuildImage task
// Usage: ./gradlew bootBuildImage
Comment on lines +81 to +82

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Stale Dockerfile left behind after migrating to bootBuildImage.

bootBuildImage produces an OCI image via Paketo buildpacks and does not use the repo's Dockerfile at all. The unpack task that populated target/dependency (which the existing Dockerfile COPYs from) has also been removed, so the Dockerfile is now both unused by the build pipeline and broken as a standalone build. Recommend deleting Dockerfile as part of this PR, or adding a comment in it stating it is no longer in use, to avoid future confusion.

2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
5 changes: 3 additions & 2 deletions src/main/java/org/kpmp/Query.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package org.kpmp;

import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import org.kpmp.repositoryDataset.RepositoryDatasetDisplay;
import org.kpmp.repositoryDataset.RepositoryDatasetService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;

@Component
public class Query implements GraphQLQueryResolver {
public class Query {

private RepositoryDatasetService repositoryDatasetService;

Expand All @@ -19,6 +19,7 @@ public Query(RepositoryDatasetService repositoryDatasetService) {
this.repositoryDatasetService = repositoryDatasetService;
}

@QueryMapping
public List<RepositoryDatasetDisplay> getRepositoryDataset() throws IOException, Exception {
return repositoryDatasetService.getRepositoryDataset();
}
Expand Down
Loading