From aeb60e116905af89b1ac883afe8a265e3773c289 Mon Sep 17 00:00:00 2001 From: Kaniska Date: Mon, 3 Aug 2026 15:53:28 +0000 Subject: [PATCH 1/3] Add workflow --- .github/workflows/test-app-token.yml | 62 ++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/test-app-token.yml diff --git a/.github/workflows/test-app-token.yml b/.github/workflows/test-app-token.yml new file mode 100644 index 000000000..ad2d0b16e --- /dev/null +++ b/.github/workflows/test-app-token.yml @@ -0,0 +1,62 @@ +name: Test app token +on: + push: + branches: + - app-token-test + +permissions: {} + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - name: Generate a token + id: app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.DEVCONTAINERS_REPO_AUTOMATION_ID }} + private-key: ${{ secrets.DEVCONTAINERS_REPO_AUTOMATION_PRIVATE_KEY }} + + - name: Verify read + contents write + env: + GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} + REPO: ${{ github.repository }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + RUN_ID: ${{ github.run_id }} + run: | + set -e + echo "Repos covered by this installation token:" + gh api /installation/repositories --jq '.repositories[].full_name' + gh api "/repos/$REPO" --jq '"read OK: " + .full_name' + REF="app-token-test-$RUN_ID" + SHA=$(gh api "/repos/$REPO/git/ref/heads/$DEFAULT_BRANCH" --jq .object.sha) + gh api --method POST "/repos/$REPO/git/refs" -f ref="refs/heads/$REF" -f sha="$SHA" + gh api --method DELETE "/repos/$REPO/git/refs/heads/$REF" + echo "contents:write OK (created + deleted refs/heads/$REF)" + + - name: Verify pull-requests write (create + close PR) + env: + GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} + REPO: ${{ github.repository }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + RUN_ID: ${{ github.run_id }} + run: | + set -e + BASE="app-token-prtest-base-$RUN_ID" + HEAD="app-token-prtest-head-$RUN_ID" + SHA=$(gh api "/repos/$REPO/git/ref/heads/$DEFAULT_BRANCH" --jq .object.sha) + gh api --method POST "/repos/$REPO/git/refs" -f ref="refs/heads/$BASE" -f sha="$SHA" + gh api --method POST "/repos/$REPO/git/refs" -f ref="refs/heads/$HEAD" -f sha="$SHA" + gh api --method PUT "/repos/$REPO/contents/.apptoken-test-$RUN_ID.txt" \ + -f message="app token PR test marker" \ + -f branch="$HEAD" \ + -f content="$(echo -n 'app-token pr creation test' | base64 -w0)" + PR=$(gh api --method POST "/repos/$REPO/pulls" \ + -f title="[TEST] app token PR creation ($RUN_ID)" \ + -f body="Automated test of pull-requests:write via GitHub App token. Auto-closed." \ + -f head="$HEAD" -f base="$BASE" -F draft=true --jq .number) + echo "pull-requests:write OK -- created PR #$PR" + gh api --method PATCH "/repos/$REPO/pulls/$PR" -f state=closed --jq '"closed PR #" + (.number|tostring)' + gh api --method DELETE "/repos/$REPO/git/refs/heads/$HEAD" + gh api --method DELETE "/repos/$REPO/git/refs/heads/$BASE" + echo "cleanup OK -- deleted $HEAD and $BASE" \ No newline at end of file From 3f016a3998f1ad1afdce645e1b73808c105a8fee Mon Sep 17 00:00:00 2001 From: Kaniska Date: Mon, 24 Aug 2026 16:47:37 +0000 Subject: [PATCH 2/3] [java] - Feature fix --- src/java/devcontainer-feature.json | 2 +- src/java/install.sh | 4 ++-- test/java/install_additional_java.sh | 1 + test/java/install_java_25.sh | 16 ++++++++++++++++ test/java/scenarios.json | 10 +++++++++- 5 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 test/java/install_java_25.sh diff --git a/src/java/devcontainer-feature.json b/src/java/devcontainer-feature.json index 3a1170df7..cfc22e0a2 100644 --- a/src/java/devcontainer-feature.json +++ b/src/java/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "java", - "version": "1.8.1", + "version": "1.8.2", "name": "Java (via SDKMAN!)", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/java", "description": "Installs Java, SDKMAN! (if not installed), and needed dependencies.", diff --git a/src/java/install.sh b/src/java/install.sh index a142ab9e3..b8b46e2fc 100644 --- a/src/java/install.sh +++ b/src/java/install.sh @@ -370,7 +370,7 @@ if [ ! -d "${SDKMAN_DIR}" ]; then updaterc "export SDKMAN_DIR=${SDKMAN_DIR}\n. \${SDKMAN_DIR}/bin/sdkman-init.sh" fi -sdk_install java ${JAVA_VERSION} "\\s*" "(\\.[a-z0-9]+)*-" ".*-[a-z]+$" "true" +sdk_install java ${JAVA_VERSION} "\\s*" "([.+][a-z0-9]+)*-" ".*-[a-z]+$" "true" # Additional java versions to be installed but not be set as default. if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then @@ -378,7 +378,7 @@ if [ ! -z "${ADDITIONAL_VERSIONS}" ]; then IFS="," read -a additional_versions <<< "$ADDITIONAL_VERSIONS" for version in "${additional_versions[@]}"; do - sdk_install java ${version} "\\s*" "(\\.[a-z0-9]+)*-" ".*-[a-z]+$" "false" + sdk_install java ${version} "\\s*" "([.+][a-z0-9]+)*-" ".*-[a-z]+$" "false" done IFS=$OLDIFS su ${USERNAME} -c ". ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk default java ${JAVA_VERSION}" diff --git a/test/java/install_additional_java.sh b/test/java/install_additional_java.sh index 882c49d1c..2e7bdaf6e 100644 --- a/test/java/install_additional_java.sh +++ b/test/java/install_additional_java.sh @@ -6,6 +6,7 @@ set -e source dev-container-features-test-lib check "java version 11 installed as default" grep "11\." <(java --version) +check "java version 25 installed" grep -E "^25\.[0-9.]+\+[0-9]+-ms$" <(ls /usr/local/sdkman/candidates/java) check "java version 17 installed" grep "^17\." <(ls /usr/local/sdkman/candidates/java) check "java version 8 installed" grep "^8\." <(ls /usr/local/sdkman/candidates/java) diff --git a/test/java/install_java_25.sh b/test/java/install_java_25.sh new file mode 100644 index 000000000..d71cabc95 --- /dev/null +++ b/test/java/install_java_25.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +echo 'public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }' > HelloWorld.java +javac HelloWorld.java + +check "hello world with Java 25" /bin/bash -c 'java HelloWorld | grep "Hello, World!"' +check "Java 25 installed as default" grep 'openjdk 25\.' <(java --version) +check "Java 25 Microsoft candidate with build metadata installed" grep -E '^25\.[0-9.]+\+[0-9]+-ms$' <(ls /usr/local/sdkman/candidates/java) + +# Report result +reportResults \ No newline at end of file diff --git a/test/java/scenarios.json b/test/java/scenarios.json index 0441f0aa6..cc570df85 100644 --- a/test/java/scenarios.json +++ b/test/java/scenarios.json @@ -16,6 +16,14 @@ } } }, + "install_java_25": { + "image": "ubuntu:noble", + "features": { + "java": { + "version": "25" + } + } + }, "install_lts_version": { "image": "ubuntu:noble", "features": { @@ -29,7 +37,7 @@ "features": { "java": { "version": "11", - "additionalVersions": "17,8" + "additionalVersions": "25,17,8" } } }, From 5a1a3aa8f901e0c8dca9e7c2cff2341eb5ef99de Mon Sep 17 00:00:00 2001 From: Kaniska Date: Mon, 24 Aug 2026 16:50:54 +0000 Subject: [PATCH 3/3] Deleting test workflow --- .github/workflows/test-app-token.yml | 62 ---------------------------- 1 file changed, 62 deletions(-) delete mode 100644 .github/workflows/test-app-token.yml diff --git a/.github/workflows/test-app-token.yml b/.github/workflows/test-app-token.yml deleted file mode 100644 index ad2d0b16e..000000000 --- a/.github/workflows/test-app-token.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Test app token -on: - push: - branches: - - app-token-test - -permissions: {} - -jobs: - verify: - runs-on: ubuntu-latest - steps: - - name: Generate a token - id: app-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ vars.DEVCONTAINERS_REPO_AUTOMATION_ID }} - private-key: ${{ secrets.DEVCONTAINERS_REPO_AUTOMATION_PRIVATE_KEY }} - - - name: Verify read + contents write - env: - GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} - REPO: ${{ github.repository }} - DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - RUN_ID: ${{ github.run_id }} - run: | - set -e - echo "Repos covered by this installation token:" - gh api /installation/repositories --jq '.repositories[].full_name' - gh api "/repos/$REPO" --jq '"read OK: " + .full_name' - REF="app-token-test-$RUN_ID" - SHA=$(gh api "/repos/$REPO/git/ref/heads/$DEFAULT_BRANCH" --jq .object.sha) - gh api --method POST "/repos/$REPO/git/refs" -f ref="refs/heads/$REF" -f sha="$SHA" - gh api --method DELETE "/repos/$REPO/git/refs/heads/$REF" - echo "contents:write OK (created + deleted refs/heads/$REF)" - - - name: Verify pull-requests write (create + close PR) - env: - GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} - REPO: ${{ github.repository }} - DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - RUN_ID: ${{ github.run_id }} - run: | - set -e - BASE="app-token-prtest-base-$RUN_ID" - HEAD="app-token-prtest-head-$RUN_ID" - SHA=$(gh api "/repos/$REPO/git/ref/heads/$DEFAULT_BRANCH" --jq .object.sha) - gh api --method POST "/repos/$REPO/git/refs" -f ref="refs/heads/$BASE" -f sha="$SHA" - gh api --method POST "/repos/$REPO/git/refs" -f ref="refs/heads/$HEAD" -f sha="$SHA" - gh api --method PUT "/repos/$REPO/contents/.apptoken-test-$RUN_ID.txt" \ - -f message="app token PR test marker" \ - -f branch="$HEAD" \ - -f content="$(echo -n 'app-token pr creation test' | base64 -w0)" - PR=$(gh api --method POST "/repos/$REPO/pulls" \ - -f title="[TEST] app token PR creation ($RUN_ID)" \ - -f body="Automated test of pull-requests:write via GitHub App token. Auto-closed." \ - -f head="$HEAD" -f base="$BASE" -F draft=true --jq .number) - echo "pull-requests:write OK -- created PR #$PR" - gh api --method PATCH "/repos/$REPO/pulls/$PR" -f state=closed --jq '"closed PR #" + (.number|tostring)' - gh api --method DELETE "/repos/$REPO/git/refs/heads/$HEAD" - gh api --method DELETE "/repos/$REPO/git/refs/heads/$BASE" - echo "cleanup OK -- deleted $HEAD and $BASE" \ No newline at end of file